import type { Context } from "hono";
import { error, success } from "@/lib/response";
import { logError } from "@/lib/logger";
import { EDMService } from "@/v1/services/admin/edm/edm.service";
import type { CreateEDMInput, UpdateEDMInput } from "@/v1/services/admin/edm/edm.service";

/** Console user id, when the route ran behind a session. Recorded as the author
 *  of a template or version; null for the unauthenticated preview route. */
const actorId = (c: Context): string | null => {
  try {
    return (c.get("consoleUser") as { id?: string } | undefined)?.id ?? null;
  } catch {
    return null;
  }
};

export const listEDMHandler = async (c: Context) => {
  try {
    const db = c.get("datastore");
    const result = await EDMService.getInstance().listTemplates(db);
    if (!result.success) {
      return error(c, result.message, (result as any).status ?? 502);
    }
    return success(c, result.data);
  } catch (err: any) {
    logError("[EDM] listEDMHandler:", err);
    return error(c, err?.message ?? "Failed to list EDM templates", 500);
  }
};

export const getEDMHandler = async (c: Context) => {
  try {
    const db = c.get("datastore");
    const templateId: any = c.req.param("templateId");
    const result = await EDMService.getInstance().getTemplate(db, templateId);
    if (!result.success) {
      const status = (result as any).status === 404 ? 404 : 502;
      return error(c, result.message, status);
    }
    return success(c, result.data);
  } catch (err: any) {
    logError("[EDM] getEDMHandler:", err);
    return error(c, err?.message ?? "Failed to get EDM template", 500);
  }
};

export const createEDMHandler = async (c: Context) => {
  try {
    const db = c.get("datastore");
    const body = await c.req.json() as CreateEDMInput;

    if (!body.name?.trim()) return error(c, "name is required", 400);
    if (!body.subject?.trim()) return error(c, "subject is required", 400);
    if (!body.html_content?.trim()) return error(c, "html_content is required", 400);

    const result = await EDMService.getInstance().createTemplate(db, body, actorId(c));

    if (!result.success) {
      const r = result as any;
      // Partial failure: template row exists but its first version did not save.
      if (r.step === "version" && r.templateId) {
        return c.json(
          {
            success: false,
            message: r.message,
            data: { templateId: r.templateId },
            partial: true,
          },
          422,
        );
      }
      return error(c, r.message, r.status ?? 502);
    }

    return success(c, result.data, "EDM template created", 201);
  } catch (err: any) {
    logError("[EDM] createEDMHandler:", err);
    return error(c, err?.message ?? "Failed to create EDM template", 500);
  }
};

export const updateEDMHandler = async (c: Context) => {
  try {
    const db = c.get("datastore");
    const templateId: any = c.req.param("templateId");
    const body = await c.req.json() as UpdateEDMInput;

    const result = await EDMService.getInstance().updateTemplate(
      db,
      templateId,
      body,
      actorId(c),
    );
    if (!result.success) {
      return error(c, result.message, (result as any).status ?? 502);
    }
    return success(c, result.data, "EDM template updated");
  } catch (err: any) {
    logError("[EDM] updateEDMHandler:", err);
    return error(c, err?.message ?? "Failed to update EDM template", 500);
  }
};

export const deleteEDMHandler = async (c: Context) => {
  try {
    const db = c.get("datastore");
    const templateId: any = c.req.param("templateId");
    const result = await EDMService.getInstance().deleteTemplate(db, templateId);
    if (!result.success) {
      return error(c, result.message, (result as any).status ?? 502);
    }
    return success(c, null, "EDM template deleted");
  } catch (err: any) {
    logError("[EDM] deleteEDMHandler:", err);
    return error(c, err?.message ?? "Failed to delete EDM template", 500);
  }
};

export const sendEDMTestHandler = async (c: Context) => {
  try {
    const db = c.get("datastore");
    const templateId: any = c.req.param("templateId");
    const body = await c.req.json() as { to?: string; template_data?: Record<string, unknown> };

    if (!body.to?.trim()) return error(c, "to is required", 400);

    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    const emails = body.to.split(',').map(e => e.trim()).filter(e => e.length > 0);

    if (emails.length === 0) return error(c, "no valid emails provided", 400);

    for (const email of emails) {
      if (!emailRegex.test(email)) return error(c, `invalid email address: ${email}`, 400);
    }

    const result = await EDMService.getInstance().sendTestEmail(
      db,
      templateId,
      emails,
      body.template_data ?? {},
    );
    if (!result.success) {
      return error(c, result.message, (result as any).status ?? 502);
    }
    return success(c, null, `Test email sent to ${body.to.trim()}`);
  } catch (err: any) {
    logError("[EDM] sendEDMTestHandler:", err);
    return error(c, err?.message ?? "Failed to send test email", 500);
  }
};

export const previewEDMHandler = async (c: Context) => {
  try {
    const db = c.get("datastore");
    const templateId: any = c.req.param("templateId");
    const isDownload = c.req.query("download") === "1" || c.req.query("download") === "true";
    const result = await EDMService.getInstance().getTemplate(db, templateId);
    if (!result.success) {
      return c.html("<h1>Template not found</h1>", 404);
    }
    const template = result.data;
    const activeVer = template.versions.find((v: any) => v.active === 1) ?? template.versions[0];

    if (!activeVer || !activeVer.html_content) {
      return c.html("<h1>No HTML content available for this template.</h1>", 404);
    }

    if (isDownload) {
      c.header("Content-Disposition", `attachment; filename="${template.name.replace(/[^a-z0-9]/gi, '_').toLowerCase() || 'edm_template'}.html"`);
      c.header("Content-Type", "text/html; charset=UTF-8");
      return c.body(activeVer.html_content);
    }

    return c.html(activeVer.html_content);
  } catch (err: any) {
    logError("[EDM] previewEDMHandler:", err);
    return c.html("<h1>Internal server error</h1>", 500);
  }
};
