"use client"

import { toastApiError } from "@/lib/toast-api-error";
import { useRouter } from "next/navigation"
import { zodResolver } from "@hookform/resolvers/zod"
import { Upload } from "lucide-react"
import * as React from "react"
import { Controller, useForm } from "react-hook-form"
import { toast } from "sonner"

import {
  FormPageHeader,
  FormPanel,
  FormSaveBar,
} from "@/app/dashboard/_components/form"
import type { SettingsSelectOption } from "@/components/settings/types"
import { SettingsSelect } from "@/components/settings/ui/settings-select"
import { Field, FieldError, FieldLabel } from "@/components/ui/field"
import {
  fetchBankApis,
  submitBankApiQuickAction,
} from "@/components/xml-apis/bank-api/api/bank-api.api"
import {
  posOcrBankCodeFromBankName,
  STANDALONE_CSV_TO_XML_BANK_ID,
  STANDALONE_JSON_TO_XML_BANK_ID,
  type BankApiQuickActionFileUploadDefinition,
} from "@/components/xml-apis/bank-api/data/bank-api-quick-actions"
import type { BankApi } from "@/components/xml-apis/bank-api/types"
import {
  bankApiQuickActionUploadSchema,
  type BankApiQuickActionUploadValues,
} from "@/components/xml-apis/bank-api/quick-action/schema"
import { validateQuickActionFiles } from "@/components/xml-apis/bank-api/quick-action/validate-quick-action-files"
import { XmlFileDropzone } from "@/components/xml-apis/shared/xml-file-dropzone"
import {
  XML_UPLOAD_MAX_FILES,
  XML_UPLOAD_MAX_FILE_SIZE_MB,
} from "@/components/xml-apis/shared/xml-upload-validation"

const listHref = "/dashboard/xml-apis/bank-api"
const PLEASE_SELECT: SettingsSelectOption = {
  value: "please-select",
  label: "Please Select",
}

type BankApiQuickActionUploadFormProps = {
  bankId: string
  bankName: string
  action: BankApiQuickActionFileUploadDefinition
}

export function BankApiQuickActionUploadForm({
  bankId,
  bankName,
  action,
}: BankApiQuickActionUploadFormProps) {
  const router = useRouter()
  const [files, setFiles] = React.useState<File[]>([])
  const [fileNames, setFileNames] = React.useState<string[]>([])
  const [fileError, setFileError] = React.useState<string | null>(null)
  const [bankApis, setBankApis] = React.useState<BankApi[]>([])
  const [bankApiOptions, setBankApiOptions] = React.useState<SettingsSelectOption[]>([
    PLEASE_SELECT,
  ])

  const requireBankSelection = Boolean(action.requireBankSelection)

  React.useEffect(() => {
    if (!requireBankSelection) return

    void fetchBankApis()
      .then((result) => {
        setBankApis(result.items)
        setBankApiOptions([
          PLEASE_SELECT,
          ...result.items.map((bankApi) => ({
            value: bankApi.id,
            label: bankApi.corporateAccount
              ? `${bankApi.bankName} (${bankApi.corporateAccount})`
              : bankApi.bankName,
          })),
        ])
      })
      .catch(() => {
        toast.error("Failed to load bank APIs")
      })
  }, [requireBankSelection])

  const form = useForm<BankApiQuickActionUploadValues>({
    resolver: zodResolver(bankApiQuickActionUploadSchema),
    defaultValues: {
      bankId,
      bankName,
      actionId: action.id,
      fileCount: 0,
      bankApiId: "please-select",
    },
    mode: "onBlur",
  })

  const {
    control,
    handleSubmit,
    setValue,
    formState: { errors, isSubmitting },
  } = form

  const applyFiles = (nextFiles: File[]) => {
    const validationError = validateQuickActionFiles(nextFiles, action)
    if (validationError) {
      setFileError(validationError)
      setFiles([])
      setFileNames([])
      setValue("fileCount", 0, { shouldValidate: true })
      return
    }

    setFileError(null)
    setFiles(nextFiles)
    setFileNames(nextFiles.map((file) => file.name))
    setValue("fileCount", nextFiles.length, { shouldValidate: true })
  }

  const isStandaloneUploadTool =
    bankId === STANDALONE_CSV_TO_XML_BANK_ID || bankId === STANDALONE_JSON_TO_XML_BANK_ID

  const onSubmit = handleSubmit(async (values) => {
    let bankCode: string | undefined

    if (requireBankSelection) {
      if (!values.bankApiId || values.bankApiId === "please-select") {
        form.setError("bankApiId", { message: "Please select a bank API" })
        return
      }

      const selected = bankApis.find((item) => item.id === values.bankApiId)
      if (!selected) {
        form.setError("bankApiId", { message: "Please select a bank API" })
        return
      }

      bankCode = posOcrBankCodeFromBankName(selected.bankName)
    }

    if (!files.length) {
      setFileError("Upload at least one file")
      return
    }

    try {
      await submitBankApiQuickAction({
        bankId,
        bankName,
        action,
        files,
        bankCode,
      })
      toast.success(`${action.label} completed`)
      router.push(listHref)
    } catch (error) {
      toastApiError(error, "Failed to upload files")
    }
  })

  return (
    <form onSubmit={(e) => void onSubmit(e)} className="pb-4">
      <FormPageHeader
        backHref={listHref}
        breadcrumb={[
          { label: "XML API" },
          { label: "Bank Api", href: listHref },
          { label: action.label },
        ]}
        titleIcon={<Upload className="size-5 text-primary" />}
        title={action.label}
        description={
          isStandaloneUploadTool
            ? action.description
            : `${bankName} — ${action.description}`
        }
      />

      <FormPanel title="Upload files">
        <div className="space-y-6">
          {requireBankSelection ? (
            <Field data-invalid={!!errors.bankApiId} className="max-w-md gap-1.5">
              <FieldLabel className="text-sm font-medium">
                Bank API <span className="text-destructive">*</span>
              </FieldLabel>
              <Controller
                name="bankApiId"
                control={control}
                render={({ field }) => (
                  <SettingsSelect
                    value={field.value ?? "please-select"}
                    onValueChange={field.onChange}
                    options={bankApiOptions}
                    placeholder="Please select"
                  />
                )}
              />
              <FieldError
                errors={
                  errors.bankApiId?.message
                    ? [{ message: String(errors.bankApiId.message) }]
                    : undefined
                }
              />
            </Field>
          ) : !isStandaloneUploadTool ? (
            <Field className="max-w-md gap-1.5">
              <FieldLabel className="text-sm font-medium">Bank name</FieldLabel>
              <p className="text-sm text-muted-foreground">{bankName}</p>
            </Field>
          ) : null}

          <Field data-invalid={!!errors.fileCount || !!fileError} className="gap-1.5">
            <XmlFileDropzone
              accept={action.accept}
              browseLabel={action.browseLabel}
              multiple={action.multiple}
              onFilesChosen={applyFiles}
              onFilesSelected={() => {}}
            />
            {fileNames.length > 0 ? (
              <ul className="text-sm text-muted-foreground">
                {fileNames.map((name) => (
                  <li key={name}>{name}</li>
                ))}
              </ul>
            ) : null}
            <p className="text-xs text-muted-foreground">
              {action.extensions.join(", ")} only · max {XML_UPLOAD_MAX_FILES} files ·{" "}
              {XML_UPLOAD_MAX_FILE_SIZE_MB}MB per file
            </p>
            <FieldError
              errors={
                fileError || errors.fileCount?.message
                  ? [{ message: String(fileError ?? errors.fileCount?.message) }]
                  : undefined
              }
            />
          </Field>
        </div>
      </FormPanel>

      <FormSaveBar
        cancelHref={listHref}
        isSaving={isSubmitting}
        saveLabel={action.submitLabel ?? "Upload files"}
        onReset={() => {
          form.reset({
            bankId,
            bankName,
            actionId: action.id,
            fileCount: 0,
            bankApiId: "please-select",
          })
          setFiles([])
          setFileNames([])
          setFileError(null)
        }}
      />
    </form>
  )
}
