import {
    useCallback,
    useEffect,
    useRef,
    useState,
} from 'react'

import * as Dialog from '@radix-ui/react-dialog'

import {
    Camera,
    X,
} from 'lucide-react'
import { MotionDialogContent } from '../../../../shared/ui/MotionDialog/MotionDialog'

import './AvatarCameraModal.scss'

type AvatarCameraModalProps = {
    open: boolean
    onClose: () => void
    onCapture: (file: File) => void
}

export function AvatarCameraModal({
    open,
    onClose,
    onCapture,
}: AvatarCameraModalProps) {
    const videoRef =
        useRef<HTMLVideoElement | null>(null)

    const streamRef =
        useRef<MediaStream | null>(null)

    const [error, setError] = useState('')

    const stopStream = useCallback(() => {
        streamRef.current
            ?.getTracks()
            .forEach((track) => track.stop())

        streamRef.current = null
    }, [])

    useEffect(() => {
        if (!open) {
            stopStream()
            return
        }

        async function initCamera() {
            try {
                setError('')

                const stream =
                    await navigator.mediaDevices.getUserMedia(
                        {
                            video: {
                                facingMode: 'user',
                            },
                            audio: false,
                        },
                    )

                streamRef.current = stream

                if (videoRef.current) {
                    videoRef.current.srcObject = stream
                }
            } catch {
                setError(
                    'Не удалось получить доступ к камере',
                )
            }
        }

        initCamera()

        return () => {
            stopStream()
        }
    }, [open, stopStream])

    async function handleCapture() {
        if (!videoRef.current) return

        const video = videoRef.current

        const canvas =
            document.createElement('canvas')

        canvas.width = video.videoWidth
        canvas.height = video.videoHeight

        const context =
            canvas.getContext('2d')

        if (!context) return

        context.drawImage(
            video,
            0,
            0,
            canvas.width,
            canvas.height,
        )

        canvas.toBlob(
            (blob) => {
                if (!blob) return

                const file = new File(
                    [blob],
                    `camera-${Date.now()}.jpg`,
                    {
                        type: 'image/jpeg',
                    },
                )

                onCapture(file)
            },
            'image/jpeg',
            0.95,
        )
    }

    return (
        <Dialog.Root
            open={open}
            onOpenChange={(next) => {
                if (!next) {
                    onClose()
                }
            }}
        >
            <MotionDialogContent
                open={open}
                overlayClassName="camera-modal__overlay"
                contentClassName="camera-modal"
            >
                    <div className="camera-modal__header">
                        <button
                            type="button"
                            onClick={onClose}
                        >
                            <X size={18} />
                        </button>
                    </div>

                    <div className="camera-modal__body">
                        {error ? (
                            <div className='camera-modal__not-found'>
                                <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
                                    <g fill="currentColor">
                                        <path d="m7.762 7.5l.41-1.268A2.5 2.5 0 0 1 10.55 4.5h2.898a2.5 2.5 0 0 1 2.379 1.732l.41 1.268H17.5A2.5 2.5 0 0 1 20 10v6a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 4 16v-6a2.5 2.5 0 0 1 2.5-2.5z" opacity=".2"></path>
                                        <path fillRule="evenodd" d="M6.172 5.232L5.762 6.5H4.5A2.5 2.5 0 0 0 2 9v6a2.5 2.5 0 0 0 2.5 2.5h11A2.5 2.5 0 0 0 18 15V9a2.5 2.5 0 0 0-2.5-2.5h-1.263l-.409-1.268a2.5 2.5 0 0 0-2.38-1.732H8.552a2.5 2.5 0 0 0-2.38 1.732M4.5 7.5h1.99l.633-1.96A1.5 1.5 0 0 1 8.551 4.5h2.898a1.5 1.5 0 0 1 1.427 1.04l.633 1.96H15.5A1.5 1.5 0 0 1 17 9v6a1.5 1.5 0 0 1-1.5 1.5h-11A1.5 1.5 0 0 1 3 15V9a1.5 1.5 0 0 1 1.5-1.5" clipRule="evenodd"></path>
                                        <path fillRule="evenodd" d="M7 11.5a3 3 0 1 0 6 0a3 3 0 0 0-6 0m5 0a2 2 0 1 1-4 0a2 2 0 0 1 4 0" clipRule="evenodd"></path>
                                        <path d="M1.15 1.878a.514.514 0 0 1 .728-.727l16.971 16.971a.514.514 0 0 1-.727.727z"></path>
                                    </g>
                                </svg>
                                {error}
                            </div>
                        ) : (
                            <video
                                ref={videoRef}
                                autoPlay
                                muted
                                playsInline
                            />
                        )}

                        <div className="camera-modal__header">
                            <button
                                type="button"
                                onClick={onClose}
                            >
                                <X size={18} />
                            </button>
                        </div>

                        <div className="camera-modal__footer">
                            <button
                                type="button"
                                onClick={handleCapture}
                                disabled={Boolean(error)}
                            >
                                <Camera size={22} />
                            </button>
                        </div>
                    </div>
            </MotionDialogContent>
        </Dialog.Root>
    )
}
