"use client";

import { isApiSuccess } from "@/lib/api-messages";
import { toastApiError } from "@/lib/toast-api-error";
import { useState } from "react";

import { useRouter } from "next/navigation";
import { zodResolver } from "@hookform/resolvers/zod";
import { Info, Plus } from "lucide-react";
import { Controller, useForm } from "react-hook-form";
import { toast } from "sonner";

import {
  FormPageHeader,
  FormPanel,
  FormSaveBar,
} from "@/app/dashboard/_components/form";
import { FormField } from "@/components/form/form-field";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import { Input } from "@/components/ui/input";
import { requestDashboardApi } from "@/lib/dashboard-api-client";

import { MasterTableDateField } from "../../_components/master-table-date-field";
import { formatMarketPriceDisplay } from "./asset-detail-form-utils";
import {
  type AssetDetailFormValues,
  bondDetailFormSchema,
  bondFundDetailFormSchema,
  commodityDetailFormSchema,
  getAssetClassLabel,
  stockDetailFormSchema,
  type AssetDetailRecord,
  type BondDetailFormValues,
  type BondFundDetailFormValues,
  type CommodityDetailFormValues,
  type StockDetailFormValues,
  type SupportedDetailAssetClass,
} from "./detail-types";
import type { MissingAssetMarketDataRow } from "./schema";

const LIST_HREF = "/dashboard/master-table/missing-asset-market-data";
const SUBMIT_HREF = "/dashboard/master-table/missing-asset-market-data/add-details/submit";

type Props = {
  marketRow: MissingAssetMarketDataRow;
  assetClass: SupportedDetailAssetClass;
  initial: AssetDetailRecord;
};

function MarketDataBanner({ row }: { row: MissingAssetMarketDataRow }) {
  return (
    <Alert className="border-sky-200 bg-sky-50/80">
      <Info className="size-4 text-sky-700" />
      <AlertTitle className="text-sky-900">Market data</AlertTitle>
      <AlertDescription className="text-sky-900/90 text-sm">
        <span className="font-mono font-medium">{row.isin}</span>
        {" · "}
        Asset class: {getAssetClassLabel(row.baseAssetClass as SupportedDetailAssetClass)}
        {" · "}
        Market price: {formatMarketPriceDisplay(row)}
        {row.marketPriceUpdated ? ` (updated ${row.marketPriceUpdated})` : null}
      </AlertDescription>
    </Alert>
  );
}

async function submitAssetDetails({
  isin,
  assetClass,
  values,
  successMessage,
  router,
}: {
  isin: string;
  assetClass: SupportedDetailAssetClass;
  values: AssetDetailFormValues;
  successMessage: string;
  router: ReturnType<typeof useRouter>;
}) {
  const data = await requestDashboardApi<{
    status?: string;
    message?: string;
  }>({
    url: SUBMIT_HREF,
    method: "POST",
    body: { isin, assetClass, values },
    fallbackError: "Could not save missing asset details.",
    validate: (payload) => isApiSuccess(payload),
  });

  toast.success(data.message ?? successMessage);
  router.push(LIST_HREF);
}

function DetailFields({
  assetClass,
  control,
}: {
  assetClass: SupportedDetailAssetClass;
  control: ReturnType<typeof useForm<StockDetailFormValues>>["control"];
}) {
  const showCountry = assetClass === "Stock" || assetClass === "Commodity";
  const showBondFields = assetClass === "Bond";

  return (
    <div className="grid gap-5 sm:grid-cols-2">
      <Controller
        name="isin"
        control={control}
        render={({ field }) => (
          <FormField label="ISIN" htmlFor="isin" className="sm:col-span-2">
            <Input id="isin" readOnly className="font-mono bg-muted" {...field} />
          </FormField>
        )}
      />

      <Controller
        name="name"
        control={control}
        render={({ field, fieldState }) => (
          <FormField label="Name" htmlFor="name" required error={fieldState.error}>
            <Input id="name" {...field} />
          </FormField>
        )}
      />

      <Controller
        name="sector"
        control={control}
        render={({ field, fieldState }) => (
          <FormField label="Sector" htmlFor="sector" required error={fieldState.error}>
            <Input id="sector" {...field} />
          </FormField>
        )}
      />

      {showCountry ? (
        <Controller
          name="country"
          control={control as never}
          render={({ field, fieldState }) => (
            <FormField label="Country" htmlFor="country" error={fieldState.error}>
              <Input id="country" {...field} />
            </FormField>
          )}
        />
      ) : null}

      <Controller
        name="industry"
        control={control}
        render={({ field, fieldState }) => (
          <FormField label="Industry" htmlFor="industry" required error={fieldState.error}>
            <Input id="industry" {...field} />
          </FormField>
        )}
      />

      <Controller
        name="marketPriceCurrency"
        control={control}
        render={({ field, fieldState }) => (
          <FormField
            label="Market price currency"
            htmlFor="marketPriceCurrency"
            required
            error={fieldState.error}
          >
            <Input id="marketPriceCurrency" placeholder="e.g. USD" {...field} />
          </FormField>
        )}
      />

      {showBondFields ? (
        <>
          <Controller
            name="bondRating"
            control={control as never}
            render={({ field, fieldState }) => (
              <FormField
                label="Bond rating"
                htmlFor="bondRating"
                required
                error={fieldState.error}
              >
                <Input id="bondRating" {...field} />
              </FormField>
            )}
          />
          <MasterTableDateField
            control={control as never}
            name={"maturity" as never}
            label="Maturity"
            htmlFor="maturity"
            required
            description="Format: YYYY-MM-DD"
          />
        </>
      ) : null}

      <Controller
        name="dividendCoupon"
        control={control}
        render={({ field, fieldState }) => (
          <FormField
            label="Dividend / coupon"
            htmlFor="dividendCoupon"
            error={fieldState.error}
            className="sm:col-span-2"
          >
            <Input id="dividendCoupon" {...field} />
          </FormField>
        )}
      />
    </div>
  );
}

export function StockDetailsForm({ marketRow, initial }: Props) {
  const router = useRouter();
  const [isSaving, setIsSaving] = useState(false);
  const isEdit = initial.hasExistingDetail;

  const form = useForm<StockDetailFormValues>({
    resolver: zodResolver(stockDetailFormSchema),
    defaultValues: initial as StockDetailFormValues,
  });

  const onSubmit = form.handleSubmit(async (values) => {
    setIsSaving(true);
    try {
      await submitAssetDetails({
        isin: marketRow.isin,
        assetClass: "Stock",
        values,
        successMessage: isEdit ? "Stock details updated" : "Stock details saved",
        router,
      });
    } catch (error) {
      toastApiError(error, "Could not save stock details.");
    } finally {
      setIsSaving(false);
    }
  });

  return (
    <form onSubmit={onSubmit} className="pb-4">
      <FormPageHeader
        backHref={LIST_HREF}
        breadcrumb={[
          { label: "Master Table" },
          { label: "Missing Asset Market Data", href: LIST_HREF },
          { label: isEdit ? "Edit stock details" : "Add stock details" },
        ]}
        titleIcon={<Plus className="size-5 text-primary" />}
        title={isEdit ? "Edit stock details" : "Add stock details"}
        description={`ISIN ${marketRow.isin}`}
      />

      <div className="mb-6">
        <MarketDataBanner row={marketRow} />
      </div>

      <FormPanel title="Stock details">
        <DetailFields assetClass="Stock" control={form.control} />
      </FormPanel>

      <FormSaveBar
        cancelHref={LIST_HREF}
        isSaving={isSaving}
        saveLabel="Save details"
        onReset={() => form.reset(initial as StockDetailFormValues)}
      />
    </form>
  );
}

export function BondDetailsForm({ marketRow, initial }: Props) {
  const router = useRouter();
  const [isSaving, setIsSaving] = useState(false);
  const isEdit = initial.hasExistingDetail;

  const form = useForm<BondDetailFormValues>({
    resolver: zodResolver(bondDetailFormSchema),
    defaultValues: initial as BondDetailFormValues,
  });

  const onSubmit = form.handleSubmit(async (values) => {
    setIsSaving(true);
    try {
      await submitAssetDetails({
        isin: marketRow.isin,
        assetClass: "Bond",
        values,
        successMessage: isEdit ? "Bond details updated" : "Bond details saved",
        router,
      });
    } catch (error) {
      toastApiError(error, "Could not save bond details.");
    } finally {
      setIsSaving(false);
    }
  });

  return (
    <form onSubmit={onSubmit} className="pb-4">
      <FormPageHeader
        backHref={LIST_HREF}
        breadcrumb={[
          { label: "Master Table" },
          { label: "Missing Asset Market Data", href: LIST_HREF },
          { label: isEdit ? "Edit bond details" : "Add bond details" },
        ]}
        titleIcon={<Plus className="size-5 text-primary" />}
        title={isEdit ? "Edit bond details" : "Add bond details"}
        description={`ISIN ${marketRow.isin}`}
      />

      <div className="mb-6">
        <MarketDataBanner row={marketRow} />
      </div>

      <FormPanel title="Bond details">
        <DetailFields assetClass="Bond" control={form.control as never} />
      </FormPanel>

      <FormSaveBar
        cancelHref={LIST_HREF}
        isSaving={isSaving}
        saveLabel="Save details"
        onReset={() => form.reset(initial as BondDetailFormValues)}
      />
    </form>
  );
}

export function BondFundDetailsForm({ marketRow, initial }: Props) {
  const router = useRouter();
  const [isSaving, setIsSaving] = useState(false);
  const isEdit = initial.hasExistingDetail;

  const form = useForm<BondFundDetailFormValues>({
    resolver: zodResolver(bondFundDetailFormSchema),
    defaultValues: initial as BondFundDetailFormValues,
  });

  const onSubmit = form.handleSubmit(async (values) => {
    setIsSaving(true);
    try {
      await submitAssetDetails({
        isin: marketRow.isin,
        assetClass: "BondFund",
        values,
        successMessage: isEdit ? "Bond fund details updated" : "Bond fund details saved",
        router,
      });
    } catch (error) {
      toastApiError(error, "Could not save bond fund details.");
    } finally {
      setIsSaving(false);
    }
  });

  return (
    <form onSubmit={onSubmit} className="pb-4">
      <FormPageHeader
        backHref={LIST_HREF}
        breadcrumb={[
          { label: "Master Table" },
          { label: "Missing Asset Market Data", href: LIST_HREF },
          { label: isEdit ? "Edit bond fund details" : "Add bond fund details" },
        ]}
        titleIcon={<Plus className="size-5 text-primary" />}
        title={isEdit ? "Edit bond fund details" : "Add bond fund details"}
        description={`ISIN ${marketRow.isin}`}
      />

      <div className="mb-6">
        <MarketDataBanner row={marketRow} />
      </div>

      <FormPanel title="Bond fund details">
        <DetailFields assetClass="BondFund" control={form.control as never} />
      </FormPanel>

      <FormSaveBar
        cancelHref={LIST_HREF}
        isSaving={isSaving}
        saveLabel="Save details"
        onReset={() => form.reset(initial as BondFundDetailFormValues)}
      />
    </form>
  );
}

export function CommodityDetailsForm({ marketRow, initial }: Props) {
  const router = useRouter();
  const [isSaving, setIsSaving] = useState(false);
  const isEdit = initial.hasExistingDetail;

  const form = useForm<CommodityDetailFormValues>({
    resolver: zodResolver(commodityDetailFormSchema),
    defaultValues: initial as CommodityDetailFormValues,
  });

  const onSubmit = form.handleSubmit(async (values) => {
    setIsSaving(true);
    try {
      await submitAssetDetails({
        isin: marketRow.isin,
        assetClass: "Commodity",
        values,
        successMessage: isEdit ? "Commodity details updated" : "Commodity details saved",
        router,
      });
    } catch (error) {
      toastApiError(error, "Could not save commodity details.");
    } finally {
      setIsSaving(false);
    }
  });

  return (
    <form onSubmit={onSubmit} className="pb-4">
      <FormPageHeader
        backHref={LIST_HREF}
        breadcrumb={[
          { label: "Master Table" },
          { label: "Missing Asset Market Data", href: LIST_HREF },
          { label: isEdit ? "Edit commodity details" : "Add commodity details" },
        ]}
        titleIcon={<Plus className="size-5 text-primary" />}
        title={isEdit ? "Edit commodity details" : "Add commodity details"}
        description={`ISIN ${marketRow.isin}`}
      />

      <div className="mb-6">
        <MarketDataBanner row={marketRow} />
      </div>

      <FormPanel title="Commodity details">
        <DetailFields assetClass="Commodity" control={form.control as never} />
      </FormPanel>

      <FormSaveBar
        cancelHref={LIST_HREF}
        isSaving={isSaving}
        saveLabel="Save details"
        onReset={() => form.reset(initial as CommodityDetailFormValues)}
      />
    </form>
  );
}

export function AssetDetailsFormRouter({
  marketRow,
  assetClass,
  initial,
}: Props) {
  const shared = { marketRow, assetClass, initial };

  switch (assetClass) {
    case "Stock":
      return <StockDetailsForm {...shared} />;
    case "Bond":
      return <BondDetailsForm {...shared} />;
    case "BondFund":
      return <BondFundDetailsForm {...shared} />;
    case "Commodity":
      return <CommodityDetailsForm {...shared} />;
  }
}
