"use client";

import { useMemo } from "react";
import { useMutation } from "@tanstack/react-query";
import { useSession } from "next-auth/react";
import { measuresList } from "@/app/db/schema/recommendations";
import { RemoteAssessmentFormValues } from "@/app/portfolio/[slug]/components/FormSchema";

interface EngineTriggerBody {
  portfolio_id: string;
  housing_type: string;
  goal: string;
  goal_value: string | null;
  trigger_file_path: string;
  already_installed_file_path: string;
  patches_file_path: string;
  non_invasive_recommendations_file_path: string;
  valuation_file_path: string;
  scenario_name: string;
  multi_plan: boolean;
  budget: number | null;
  event_type: string;
  inclusions: (typeof measuresList)[number][];
  scenario_id?: string | null;
}

/* ---------- Helpers ---------- */

async function uploadCsvToS3({
  presignedUrl,
  file,
}: {
  presignedUrl: string;
  file: Blob;
}) {
  const response = await fetch(presignedUrl, {
    method: "PUT",
    body: file,
    headers: { "Content-Type": "text/csv" },
  });

  if (!response.ok) {
    console.error(response);
    throw new Error("Failed to upload CSV to S3");
  }
  return { success: true };
}

async function generatePresignedUrl({
  userId,
  portfolioId,
  fileKey,
}: {
  userId: string;
  portfolioId: string;
  fileKey: string;
}) {
  const response = await fetch("/api/upload/csv", {
    method: "POST",
    body: JSON.stringify({ userId, portfolioId, fileKey }),
  });

  if (!response.ok) {
    throw new Error("Failed to generate presigned URL");
  }

  const data = await response.json();
  return { ...data, fileKey };
}

function generateS3Keys(userId: string, portfolioId: string) {
  const timestamp = new Date().toISOString().replace(/[:.-]/g, "");
  return {
    assetListFileKey: `${userId}/${portfolioId}/${timestamp}/asset_list.csv`,
    valuationDataFileKey: `${userId}/${portfolioId}/${timestamp}/valuation_data.csv`,
  };
}

const convertToCSV = <T extends Record<string, any>>(data: T[]): string => {
  if (data.length === 0) return "";
  const headers = Object.keys(data[0]) as (keyof T)[];
  const escape = (val: any) =>
    val == null
      ? ""
      : /[",\n]/.test(String(val))
        ? `"${String(val).replace(/"/g, '""')}"`
        : String(val);
  return [
    headers.join(","),
    ...data.map((r) => headers.map((h) => escape(r[h])).join(",")),
  ].join("\n");
};

/* ---------- Main Hook ---------- */

function useCreateRemoteAssessment({
  portfolioId,
  uprn,
  addressLineOne,
  postcode,
  valuation,
  propertyType,
  builtForm,
  measures,
  scenarioId,
}: {
  portfolioId: string;
  uprn: number | undefined | null;
  addressLineOne: string;
  postcode: string;
  valuation: number | undefined | null;
  measures: (typeof measuresList)[number][];
  propertyType?: string | null;
  builtForm?: string | null;
  scenarioId?: string | null;
}) {
  const { data: session } = useSession();
  const userId = String(session?.user.dbId);

  if (uprn === undefined || valuation === undefined) {
    console.warn("Missing UPRN or valuation, cannot proceed");
  }

  const { assetListFileKey, valuationDataFileKey } = useMemo(
    () => generateS3Keys(userId, portfolioId),
    [userId, portfolioId],
  );

  const uploadFileMutation = useMutation({
    mutationFn: async ({
      userId,
      portfolioId,
      fileKey,
      csvFile,
    }: {
      userId: string;
      portfolioId: string;
      fileKey: string;
      csvFile: Blob;
    }) => {
      // 1) Get presigned URL
      const { url } = await generatePresignedUrl({
        userId,
        portfolioId,
        fileKey,
      });

      // 2) Upload to S3
      await uploadCsvToS3({
        presignedUrl: url,
        file: csvFile,
      });

      return true;
    },
  });

  async function triggerEngine(data: RemoteAssessmentFormValues) {
    const triggerBody: EngineTriggerBody = {
      scenario_id: scenarioId === "__new__" ? null : scenarioId,
      portfolio_id: portfolioId,
      housing_type: data.housingType,
      goal: data.goal,
      goal_value: data.goalValue || null,
      trigger_file_path: assetListFileKey,
      already_installed_file_path: "",
      patches_file_path: "",
      non_invasive_recommendations_file_path: "",
      valuation_file_path: valuation ? valuationDataFileKey : "", // We only pass a valution filepath if we have a valuation
      scenario_name: data.scenario,
      inclusions: data.measures,
      multi_plan: true,
      budget: data.budget || null,
      event_type: "remote_assessment",
    };

    const response = await fetch("/api/plan/trigger", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(triggerBody),
    });

    if (!response.ok) throw new Error("Failed to trigger engine");
  }

  async function handleSubmit(formData: RemoteAssessmentFormValues) {
    // Build asset CSV
    const assetList = [
      {
        uprn,
        address: addressLineOne,
        postcode,
        ...(propertyType && { property_type: propertyType }),
        ...(builtForm && { built_form: builtForm }),
      },
    ];

    const assetCsv = new Blob([convertToCSV(assetList)], {
      type: "text/csv",
    });

    // Build valuation CSV
    const valuationCsv = new Blob([convertToCSV([{ uprn, valuation }])], {
      type: "text/csv",
    });

    // Upload asset list and valuation data and wait
    await Promise.all([
      uploadFileMutation.mutateAsync({
        userId,
        portfolioId,
        fileKey: assetListFileKey,
        csvFile: assetCsv,
      }),
      uploadFileMutation.mutateAsync({
        userId,
        portfolioId,
        fileKey: valuationDataFileKey,
        csvFile: valuationCsv,
      }),
    ]);

    // Now trigger engine (files guaranteed in S3)
    await triggerEngine(formData);
  }

  return {
    handleSubmit,
    triggerEngine,
    isUploading: uploadFileMutation.isPending,
    hasError: uploadFileMutation.isError,
  };
}

export default useCreateRemoteAssessment;
