import type { Request, Response, NextFunction } from "express";
import { z } from "zod";
import { ShopService } from "../services/ShopService.js";
import path from "path";
import fs from "fs";
import { createFieldsUploadMiddleware } from "../middleware/upload.middleware.js";
import { syncShopSeederFile } from "../utils/seederSync.js";

const shopService = new ShopService();

const indianMobileRegex = /^(?:(?:\+?91)|0)?[6-9]\d{9}$/;

const updateShopSchema = z.object({
    shopName: z.string().trim().min(1, "Shop name is required"),
    shortName: z
        .string()
        .trim()
        .max(3, "Short name can be at most 3 characters")
        .optional()
        .default("AVS"),
    godName1: z.string().trim().optional(),
    godName2: z.string().trim().optional(),
    godName3: z.string().trim().optional(),
    mobile: z
        .string()
        .trim()
        .refine((val) => indianMobileRegex.test(val), {
            message: "Please enter a valid 10-digit Indian mobile number",
        }),
    mobile2: z.string().trim().optional(),
    mapUrl: z.string().trim().optional(),
    address: z.string().trim().optional(),
});

// Separate folders per file type
const LOGO_LOCATION = "uploads/logos";
const GOD_IMAGE_LOCATION = "uploads/god-images";
const SIGN_LOCATION = "uploads/signatures";
const logoDir = path.join(process.cwd(), LOGO_LOCATION);
const godImageDir = path.join(process.cwd(), GOD_IMAGE_LOCATION);
const signDir = path.join(process.cwd(), SIGN_LOCATION);
const baseUrl = process.env.BASE_URL || "http://localhost:5000";
export class ShopController {

    /**
     * Upload Middleware — handles logo, godImage1, godImage2, and authorizedSign fields
     * from the same multipart request, each going to its designated folder.
     */
    handleImageUpload = createFieldsUploadMiddleware([
        { name: "logo", folder: LOGO_LOCATION, prefix: "logo" },
        { name: "godImage1", folder: GOD_IMAGE_LOCATION, prefix: "god1" },
        { name: "godImage2", folder: GOD_IMAGE_LOCATION, prefix: "god2" },
        { name: "authorizedSign", folder: SIGN_LOCATION, prefix: "sign" },
    ]);

    /**
     * Get Shop
     */
    async get(
        req: Request,
        res: Response,
        next: NextFunction
    ) {
        try {

            const shop = await shopService.getShop();

            if (!shop) {
                return res.status(404).json({
                    success: false,
                    message: "Shop not found.",
                    data: null,
                });
            }

            return res.json({
                success: true,
                message: "Shop fetched successfully.",
                data: {
                    ...shop,
                    logoUrl: shop.logo
                        ? `${baseUrl}/${LOGO_LOCATION}/${shop.logo}`
                        : null,
                    godImage1Url: shop.godImage1
                        ? `${baseUrl}/${GOD_IMAGE_LOCATION}/${shop.godImage1}`
                        : null,
                    godImage2Url: shop.godImage2
                        ? `${baseUrl}/${GOD_IMAGE_LOCATION}/${shop.godImage2}`
                        : null,
                    authorizedSignUrl: shop.authorizedSign
                        ? `${baseUrl}/${SIGN_LOCATION}/${shop.authorizedSign}`
                        : null,
                },
            });

        } catch (error) {
            next(error);
        }
    }

    /**
     * Create / Update Shop
     */
    async save(
        req: Request,
        res: Response,
        next: NextFunction
    ) {
        try {
            const parsed = updateShopSchema.safeParse(req.body);
            if (!parsed.success) {
                const files = req.files as { [field: string]: Express.Multer.File[] } | undefined;
                [
                    ...(files?.logo ?? []),
                    ...(files?.godImage1 ?? []),
                    ...(files?.godImage2 ?? []),
                    ...(files?.authorizedSign ?? []),
                ].forEach((f) => {
                    if (fs.existsSync(f.path)) {
                        fs.unlinkSync(f.path);
                    }
                });
                return res.status(400).json({
                    success: false,
                    message: "Validation failed",
                    errors: parsed.error.flatten().fieldErrors,
                });
            }

            const {
                shopName,
                shortName,
                godName1,
                godName2,
                godName3,
                address,
                mobile,
                mobile2,
                mapUrl,
            } = parsed.data;

            const existing = await shopService.getShop();

            // req.files is a map of fieldname -> file[] when using .fields()
            const files = req.files as { [field: string]: Express.Multer.File[] } | undefined;
            const logoFile = files?.logo?.[0];
            const godImage1File = files?.godImage1?.[0];
            const godImage2File = files?.godImage2?.[0];
            const signFile = files?.authorizedSign?.[0];

            let logo = existing?.logo ?? "default-logo.png";
            let godImage1 = existing?.godImage1 ?? "default-god1.png";
            let godImage2 = existing?.godImage2 ?? "default-god2.png";
            let authorizedSign = existing?.authorizedSign ?? null;

            // New Logo Uploaded
            if (logoFile) {
                if (
                    existing?.logo &&
                    existing.logo !== "default-logo.png"
                ) {
                    const oldLogo = path.join(logoDir, existing.logo);
                    if (fs.existsSync(oldLogo)) {
                        fs.unlinkSync(oldLogo);
                    }
                }

                logo = logoFile.filename;
            }

            // New God Image 1 Uploaded
            if (godImage1File) {
                const defaultGod1Path = path.join(godImageDir, "default-god1.png");
                fs.copyFileSync(godImage1File.path, defaultGod1Path);
                godImage1 = "default-god1.png";
            }

            // New God Image 2 Uploaded
            if (godImage2File) {
                const defaultGod2Path = path.join(godImageDir, "default-god2.png");
                fs.copyFileSync(godImage2File.path, defaultGod2Path);
                godImage2 = "default-god2.png";
            }

            // New Signature Uploaded
            if (signFile) {
                if (existing?.authorizedSign) {
                    const oldSign = path.join(signDir, existing.authorizedSign);
                    if (fs.existsSync(oldSign)) {
                        fs.unlinkSync(oldSign);
                    }
                }

                authorizedSign = signFile.filename;
            }

            const shop = await shopService.saveShop({
                shopName,
                shortName: (shortName?.trim() || "AVS").slice(0, 3),
                godName1,
                godName2,
                godName3,
                address,
                mobile,
                mobile2,
                mapUrl,
                logo,
                godImage1,
                godImage2,
                authorizedSign,
                createdBy: req.user?.id ? BigInt(req.user.id) : undefined,
            } as any);

            // Sync seeder file whenever shop is updated or new images uploaded
            syncShopSeederFile(shop);

            return res.json({
                success: true,
                message: existing
                    ? "Shop updated successfully."
                    : "Shop created successfully.",
                data: {
                    ...shop,
                    logoUrl: shop.logo
                        ? `${baseUrl}/${LOGO_LOCATION}/${shop.logo}`
                        : null,
                    godImage1Url: shop.godImage1
                        ? `${baseUrl}/${GOD_IMAGE_LOCATION}/${shop.godImage1}`
                        : null,
                    godImage2Url: shop.godImage2
                        ? `${baseUrl}/${GOD_IMAGE_LOCATION}/${shop.godImage2}`
                        : null,
                    authorizedSignUrl: shop.authorizedSign
                        ? `${baseUrl}/${SIGN_LOCATION}/${shop.authorizedSign}`
                        : null,
                },
            });

        } catch (error) {

            // Delete uploaded files if DB save fails
            const files = req.files as { [field: string]: Express.Multer.File[] } | undefined;
            [
                ...(files?.logo ?? []),
                ...(files?.godImage1 ?? []),
                ...(files?.godImage2 ?? []),
                ...(files?.authorizedSign ?? []),
            ].forEach((f) => {
                if (fs.existsSync(f.path)) {
                    fs.unlinkSync(f.path);
                }
            });

            next(error);
        }
    }
}