/** @odoo-module */

import { PartnerDetailsEdit } from "@point_of_sale/app/screens/partner_list/partner_editor/partner_editor";
import { patch } from "@web/core/utils/patch";
import { getDataURLFromFile } from "@web/core/utils/urls";
import { ErrorPopup } from "@point_of_sale/app/errors/popups/error_popup";
import { _t } from "@web/core/l10n/translation";
import { loadImage } from "@point_of_sale/utils";
import { useRef, useState, onWillUnmount } from "@odoo/owl";

patch(PartnerDetailsEdit.prototype, {
    setup() {
        super.setup(...arguments);
        this.changes.image_face_1 = this.changes.image_face_1 || false;
        this.changes.image_face_2 = this.changes.image_face_2 || false;
        this.changes.image_face_3 = this.changes.image_face_3 || false;

        this.camera = useState({
            activeField: null,
        });
        this.videoRef = useRef("video");

        onWillUnmount(() => {
            this.stopCamera();
        });
    },

    async startCamera(fieldName) {
        if (this.camera.activeField) {
            this.stopCamera();
        }
        try {
            const stream = await navigator.mediaDevices.getUserMedia({ video: true });
            this.camera.activeField = fieldName;
            this.stream = stream;
            // Wait for the video element to be rendered
            await Promise.resolve();
            // We might need a small delay or rely on the ref being attached on render
            // Since we set state, a render will happen. The ref should be available after render.
            // However, in Owl, refs are usually available after patch.
            // Let's try setting it in a next tick or just relying on the template to use the ref.
            // Actually, we need to set srcObject.
            setTimeout(() => {
                if (this.videoRef.el) {
                    this.videoRef.el.srcObject = stream;
                }
            }, 100);
        } catch (err) {
            console.error("Camera error", err);
            this.popup.add(ErrorPopup, { title: _t("Camera Error"), body: _t("Could not access camera.") });
        }
    },

    stopCamera() {
        if (this.stream) {
            this.stream.getTracks().forEach(track => track.stop());
            this.stream = null;
        }
        this.camera.activeField = null;
    },

    capturePhoto() {
        if (!this.videoRef.el) return;
        const video = this.videoRef.el;
        const canvas = document.createElement("canvas");
        canvas.width = video.videoWidth;
        canvas.height = video.videoHeight;
        const ctx = canvas.getContext("2d");
        ctx.drawImage(video, 0, 0);

        const dataUrl = canvas.toDataURL('image/jpeg');
        // Remove data:image/jpeg;base64, prefix
        this.changes[this.camera.activeField] = dataUrl.split(',')[1];
        this.stopCamera();
    },

    async uploadFaceImage(event, fieldName) {
        const file = event.target.files[0];
        if (!file) return;

        if (!file.type.match(/image.*/)) {
            await this.popup.add(ErrorPopup, {
                title: _t("Unsupported File Format"),
                body: _t("Only web-compatible Image formats such as .png or .jpeg are supported."),
            });
            return;
        }

        const imageUrl = await getDataURLFromFile(file);
        const loadedImage = await loadImage(imageUrl, {
            onError: () => {
                this.popup.add(ErrorPopup, {
                    title: _t("Loading Image Error"),
                    body: _t("Encountered error when loading image. Please try again."),
                });
            }
        });

        if (loadedImage) {
            // Resize to reasonable size for face recognition (e.g. 800x600 is usually enough)
            const resizedImage = await this._resizeImage(loadedImage, 800, 600);
            const dataUrl = resizedImage.toDataURL();
            // Remove data:image/png;base64, prefix
            this.changes[fieldName] = dataUrl.split(',')[1];
        }
    }
});
