import { Request, Response, NextFunction, RequestHandler } from "express";
import { flattenPageKeys } from "../utils/KeysHekper";
import { CustomPage } from "../models/CustomPage";
import { Language } from "../models/Language";
import { QueryBuilder } from "objection";
import fetch from "node-fetch";
import fs from "fs";
import path from "path";
import { generateContent } from "../scripts/content-generator";
import { pingPageChange } from "../services/indexingService";

interface CustomPageRequestBody {
  page_name: string;
  page_slug: string;
  meta_title: string;
  meta_description: string;
  title: string;
  description: string;
  heading_1?: string;
  subtext?: string;
  is_active: string | boolean;
  is_index: "index" | "non_index";
  lang: string;
  file_name: string;
  custom_fields?: { key: string; type: string; value: string }[];
  page_head_tag?: string;
  before_body_tag?: string;
  canonical?: string;
  noindex?: boolean;
}

function formatMySQLDate(date: Date) {
  return date.toISOString().slice(0, 19).replace("T", " ");
}
export class CustomPageController {
  private sendError(res: Response, status: number, message: string): void {
    res.status(status).json({ message });
  }

  private sendSuccess(res: Response, message: string, data?: any): void {
    res.status(200).json({ success: true, message, data });
  }

  add: RequestHandler = async (
    req: Request,
    res: Response,
    next: NextFunction
  ): Promise<void> => {
    const now = formatMySQLDate(new Date());

    try {
      const FRONTEND_GENERATOR_URL = `${process.env.FRONTEND_DOMAIN}/api/generate-custom`;
      const FRONTEND_API_SECRET = process.env.FRONTEND_API_SECRET || "";
      console.log("Frontend URL:", FRONTEND_GENERATOR_URL);
      const request = req.body as CustomPageRequestBody;

      // Validate required fields
      const requiredFields = [
        "page_name",
        "page_slug",
        "meta_title",
        "meta_description",
        "title",
        "description",
        "file_name",
        "lang",
      ];
      const missingFields = requiredFields.filter(
        (field) => !(field in request)
      );
      if (missingFields.length) {
        res.status(400).json({
          message: `Missing required fields: ${missingFields.join(", ")}`,
        });
        return;
      }

      // Validate language
      const language = await Language.query().findOne(
        "lang_code",
        request.lang
      );
      if (!language) {
        res
          .status(400)
          .json({ message: `Invalid language code: ${request.lang}` });
        return;
      }

      // Check for existing records WITHIN the same language
      const [existingCustomName, existingPageSlug, existingFileName] =
        await Promise.all([
          CustomPage.query().findOne({
            page_name: request.page_name,
            lang: language.id,
          }),
          CustomPage.query().findOne({
            page_slug: request.page_slug,
            lang: language.id,
          }),
          CustomPage.query().findOne({
            page_file_name: request.file_name,
            lang: language.id,
          }),
        ]);

      if (existingCustomName) {
        res.status(409).json({
          message: `Custom name "${request.page_name}" already exists in language "${request.lang}".`,
        });
        return;
      }
      if (existingPageSlug) {
        res.status(409).json({
          message: `Page slug "${request.page_slug}" already exists in language "${request.lang}".`,
        });
        return;
      }
      if (existingFileName) {
        res.status(409).json({
          message: `File name "${request.file_name}" already exists in language "${request.lang}".`,
        });
        return;
      }

      // Handle custom fields
      let pageKeys: { key: string; type: string; value: string }[] = [];
      if (Array.isArray(request.custom_fields)) {
        const isValid = request.custom_fields.every(
          (field) =>
            typeof field === "object" &&
            typeof field.key === "string" &&
            typeof field.type === "string" &&
            typeof field.value === "string"
        );
        if (!isValid) {
          res.status(400).json({ message: "Invalid custom_fields format" });
          return;
        }
        pageKeys = request.custom_fields;
      }

      // Add default 'whyus' keys if not already present
      const defaultWhyUsKeys = [
        { key: "whyus_title", type: "input", value: "" },
        { key: "whyus_subtitle", type: "input", value: "" },
        { key: "whyus_text", type: "rich-textarea", value: "" },
      ];

      defaultWhyUsKeys.forEach(defaultKey => {
        if (!pageKeys.some(pk => pk.key === defaultKey.key)) {
          pageKeys.push(defaultKey);
        }
      });

      // Add default 'faq' keys if not already present
      const defaultFaqKeys = [
        { key: "faq_title", type: "input", value: "" },
        { key: "faq_subtitle", type: "input", value: "" },
      ];

      defaultFaqKeys.forEach(defaultKey => {
        if (!pageKeys.some(pk => pk.key === defaultKey.key)) {
          pageKeys.push(defaultKey);
        }
      });

      // Normalize flags
      const isActive = request.is_active === "1" || request.is_active === true;

      // Insert into database
      const customPage = await CustomPage.query().insert({
        page_name: request.page_name,
        page_slug: request.page_slug,
        meta_title: request.meta_title,
        meta_description: request.meta_description,
        title: request.title,
        description: request.description,
        heading_1: request.heading_1,
        subtext: request.subtext,
        is_active: isActive,
        lang: language.id,
        page_file_name: request.file_name,
        page_keys: pageKeys,
        page_head_tag: request.page_head_tag,
        before_body_tag: request.before_body_tag,
        canonical: request.canonical,
        noindex: request.noindex ?? false,
        // created_at: now,
        updated_at: new Date().toISOString(),
      });

      generateContent().catch((e) => console.error("Error auto-generating content after custom page create:", e));

      if (customPage.is_active && !customPage.noindex) {
        pingPageChange(customPage.page_slug, "URL_UPDATED").catch((e) =>
          console.error("Error pinging Google Indexing API after custom page create:", e)
        );
      }

      // Notify frontend to generate file
      try {
        const generatorRes = await fetch(FRONTEND_GENERATOR_URL, {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            Authorization: `Bearer ${FRONTEND_API_SECRET}`,
          },
          body: JSON.stringify({
            slug: request.page_slug,
            title: request.page_name,
            content: request.description,
            file_name: request.file_name,
            page_name: request.page_name,
            lang: request.lang || process.env.APP_LANG, // default to English
            type: "custom",
          }),
        });

        if (!generatorRes.ok) {
          const errorText = await generatorRes.text();
          console.warn(
            "⚠️ Failed to trigger frontend generator:",
            generatorRes.status,
            errorText
          );
        } else {
          console.log("✅ Page generation triggered successfully on frontend.");
        }
      } catch (err) {
        console.error("❌ Error notifying frontend:", err);
      }

      res.status(201).json({
        message: "Custom page created successfully",
        data: customPage,
      });
    } catch (error) {
      console.error("Error creating custom page:", error);
      res.status(500).json({ message: "Failed to create custom page" });
    }
  };

  show: RequestHandler = async (
    req: Request,
    res: Response,
    next: NextFunction
  ): Promise<void> => {
    try {
      const customPages = await CustomPage.query()
        .select(
          "custom_pages.id",
          "custom_pages.page_name",
          "custom_pages.page_slug",
          "custom_pages.page_file_name",
          "custom_pages.meta_title",
          "custom_pages.title",
          "custom_pages.is_active",
          "custom_pages.lang",
          "language.name as language_name"
        )
        .leftJoin("languages as language", "custom_pages.lang", "language.id");

      const result = customPages.map((page: any) => ({
        id: page.id,
        page_name: page.page_name,
        page_slug: page.page_slug,
        page_file_name: page.page_file_name,
        meta_title: page.meta_title,
        title: page.title,
        is_active: page.is_active,
        lang: page.lang,
        language: page.language_name ?? null,
      }));

      this.sendSuccess(res, "Custom pages fetched successfully", result);
    } catch (error) {
      console.error("Error fetching custom pages:", error);
      next(error);
    }
  };

  showCustom: RequestHandler = async (
    req: Request,
    res: Response,
    next: NextFunction
  ): Promise<void> => {
    try {
      const { id } = req.params;

      if (!id) {
        this.sendError(res, 400, "Missing custom page ID");
        return;
      }

      const customPage = await CustomPage.query()
        .findById(id)
        .select(
          "custom_pages.*",
          "language.name as language_name",
          "language.lang_code as language_code"
        )
        .leftJoin("languages as language", "custom_pages.lang", "language.id")
        .first();

      if (!customPage) {
        this.sendError(res, 404, "Custom page not found");
        return;
      }

      this.sendSuccess(res, "Custom page fetched successfully", {
        ...customPage,
        language: {
          name: customPage.language_name,
          lang_code: customPage.language_code,
        },
        page_head_tag: customPage.page_head_tag ?? null,
        before_body_tag: customPage.before_body_tag ?? null,
      });
    } catch (error) {
      console.error("Error fetching custom page:", error);
      this.sendError(res, 500, "Internal server error");
    }
  };

  edit: RequestHandler = async (req, res, next) => {
    const now = formatMySQLDate(new Date());

    try {
      const { id } = req.params;
      const request = req.body as Partial<CustomPageRequestBody>;

      if (!id) return this.sendError(res, 400, "Missing custom page ID");

      const currentCustom = await CustomPage.query().findById(id);
      if (!currentCustom) return this.sendError(res, 404, "Custom not found");

      // Validate language if updated
      let languageId = currentCustom.lang;
      if (request.lang && request.lang !== currentCustom.lang) {
        const lang = await Language.query().findOne("lang_code", request.lang);
        if (!lang) return this.sendError(res, 400, "Invalid language code");
        languageId = lang.id;
      }

      // Check for duplicates within the same language
      const [duplicateName, duplicateSlug, duplicateFile] = await Promise.all([
        request.page_name
          ? CustomPage.query()
              .findOne({ page_name: request.page_name, lang: languageId })
              .whereNot("id", id)
          : null,
        request.page_slug
          ? CustomPage.query()
              .findOne({ page_slug: request.page_slug, lang: languageId })
              .whereNot("id", id)
          : null,
        request.file_name
          ? CustomPage.query()
              .findOne({ page_file_name: request.file_name, lang: languageId })
              .whereNot("id", id)
          : null,
      ]);

      if (duplicateName)
        return this.sendError(
          res,
          409,
          `Custom name "${request.page_name}" already exists in this language.`
        );
      if (duplicateSlug)
        return this.sendError(
          res,
          409,
          `Page slug "${request.page_slug}" already exists in this language.`
        );
      if (duplicateFile)
        return this.sendError(
          res,
          409,
          `File name "${request.file_name}" already exists in this language.`
        );
      // Update the Custom Page
      const updated = await CustomPage.query().patchAndFetchById(id, {
        page_name: request.page_name ?? currentCustom.page_name,
        page_slug: request.page_slug ?? currentCustom.page_slug,
        meta_title: request.meta_title ?? currentCustom.meta_title,
        meta_description:
          request.meta_description ?? currentCustom.meta_description,
        title: request.title ?? currentCustom.title,
        description: request.description ?? currentCustom.description,
        heading_1: request.heading_1 ?? currentCustom.heading_1,
        subtext: request.subtext ?? currentCustom.subtext,
        is_active:
          request.is_active !== undefined
            ? request.is_active === "1" || request.is_active === true
            : currentCustom.is_active,
        lang: languageId,
        page_file_name: request.file_name ?? currentCustom.page_file_name,
        page_keys: request.custom_fields ?? currentCustom.page_keys,
        page_head_tag: request.page_head_tag ?? currentCustom.page_head_tag,
        before_body_tag: request.before_body_tag ?? currentCustom.before_body_tag,
        canonical: request.canonical ?? currentCustom.canonical,
        noindex: request.noindex !== undefined ? request.noindex : currentCustom.noindex,
        updated_at: new Date().toISOString(),
      });

      generateContent().catch((e) => console.error("Error auto-generating content after custom page update:", e));

      // Trigger Google Indexing API ping
      if (currentCustom.page_slug && currentCustom.page_slug !== updated.page_slug) {
        pingPageChange(currentCustom.page_slug, "URL_DELETED").catch((e) =>
          console.error("Error pinging Google Indexing API after custom page slug rename (delete old):", e)
        );
      }

      if (updated.is_active && !updated.noindex) {
        pingPageChange(updated.page_slug, "URL_UPDATED").catch((e) =>
          console.error("Error pinging Google Indexing API after custom page update:", e)
        );
      } else {
        pingPageChange(updated.page_slug, "URL_DELETED").catch((e) =>
          console.error("Error pinging Google Indexing API after custom page deactivation:", e)
        );
      }

      // Notify frontend to regenerate or move the page
      // Replace the fetch block in edit with:
      // const frontendRes = await fetch(
      //   `${process.env.FRONTEND_DOMAIN}/api/generate-custom`,
      //   {
      //     method: "POST",
      //     headers: {
      //       "Content-Type": "application/json",
      //       Authorization: `Bearer ${process.env.FRONTEND_API_SECRET}`,
      //     },
      //     body: JSON.stringify({
      //       slug: updated.page_slug,
      //       title: updated.page_name,
      //       content: updated.description,
      //       file_name: updated.page_file_name,
      //       previous_slug: currentCustom.page_slug,
      //       lang: request.lang ?? currentCustom.lang,
      //       page_name: updated.page_name,
      //     }),
      //   }
      // );

      // if (!frontendRes.ok) {
      //   const msg = await frontendRes.text();
      //   console.warn("⚠️ Frontend update failed:", frontendRes.status, msg);
      // }

      res
        .status(200)
        .json({ message: "Custom updated successfully", data: updated });
    } catch (err) {
      console.error("Error updating custom page:", err);
      this.sendError(res, 500, "Internal server error");
    }
  };

  delete: RequestHandler = async (
    req: Request,
    res: Response,
    next: NextFunction
  ): Promise<void> => {
    try {
      const { id } = req.params;

      if (!id) {
        this.sendError(res, 400, "Missing custom page ID");
        return;
      }

      const customPage = await CustomPage.query().findById(id);
      if (!customPage) {
        this.sendError(res, 404, "Custom page not found");
        return;
      }
      console.log("Delete Custom Page", customPage);
      await CustomPage.query().deleteById(id);

      generateContent().catch((e) => console.error("Error auto-generating content after custom page delete:", e));

      if (customPage.page_slug) {
        pingPageChange(customPage.page_slug, "URL_DELETED").catch((e) =>
          console.error("Error pinging Google Indexing API after custom page delete:", e)
        );
      }

      this.sendSuccess(res, "Custom page deleted successfully");
    } catch (error) {
      console.error("Error deleting custom page:", error);
      this.sendError(res, 500, "Failed to delete custom page");
    }
  };

  getCutsomWithLang: RequestHandler = async (
    req: Request,
    res: Response,
    next: NextFunction
  ): Promise<void> => {
    try {
      const { slug, lang = process.env.APP_LANG } = req.query;

      console.log("🌐 Incoming query parameters:", { slug, lang });

      if (!slug || typeof slug !== "string") {
        res.status(400).json({ message: "Missing or invalid slug parameter" });
        return;
      }

      // Find Language by lang_code like 'en', 'es', etc.
      const language = await Language.query().where("lang_code", lang).first();

      if (!language) {
        res.status(400).json({ message: "Invalid language code" });
        return;
      }

      // const effectiveSlug =
      //   lang === process.env.APP_LANG ? slug : `${slug}/${lang}`;

      const tool = await CustomPage.query()
        .where("page_slug", slug)
        .andWhere("lang", language.id)
        .andWhere("is_active", 1)
        .first();

      if (!tool) {
        console.warn("⚠️ Custom Page not found for:", {
          page_slug: slug,
          lang: language.id,
        });
        res.status(404).json({ message: "Custom Page not found" });
        return;
      }
      const custom_keys = flattenPageKeys(tool.page_keys);
      // Return structured data
      const responseData = {
        id: tool.id,
        title: tool.meta_title,
        description: tool.meta_description,
        heading_1: tool.heading_1,
        subtext: tool.subtext,
        slug: tool.page_slug,
        lang: language.lang_code,
        page_name: tool.page_name,
        is_index: tool.is_index,
        page_keys: custom_keys,
        type: "custom",
        page_head_tag: tool.page_head_tag,
        before_body_tag: tool.before_body_tag,
        canonical: tool.canonical,
        noindex: tool.noindex ?? false,
      };

      console.log("✅ Language page response:", responseData);
      res.json(responseData);
    } catch (err) {
      console.error("❌ Failed to fetch tool with lang:", err);
      res.status(500).json({ message: "Internal server error" });
    }
  };

  getPageNames: RequestHandler = async (
    req: Request,
    res: Response,
    next: NextFunction
  ): Promise<void> => {
    try {
      const filePath = path.join(__dirname, "../../project_pages.txt");
      const data = fs.readFileSync(filePath, "utf8");
      const pageNames = data.split("\n").filter(name => name.trim() !== "");
      this.sendSuccess(res, "Page names fetched successfully", pageNames);
    } catch (error) {
      console.error("Error fetching page names:", error);
      this.sendError(res, 500, "Failed to fetch page names");
    }
  };
}
