"use client"

import { toastApiError } from "@/lib/toast-api-error";
import Link from "next/link"
import { Archive, FileCode2, Loader2, Trash2, X } from "lucide-react"
import * as React from "react"
import { toast } from "sonner"

import {
  FormPageHeader,
  FormPanel,
} from "@/app/dashboard/_components/form"
import { Button } from "@/components/ui/button"
import { Field, FieldError, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { submitBankApiTxtToXml } from "@/components/xml-apis/bank-api/api/bank-api.api"
import type { BankApiQuickActionTxtToXmlDefinition } from "@/components/xml-apis/bank-api/data/bank-api-quick-actions"
import {
  getUbsTxtXmlOutputOption,
  getUbsTxtXmlPrefixes,
  UBS_TXT_XML_OUTPUT_OPTIONS,
  type UbsTxtXmlOutputType,
} from "@/components/xml-apis/bank-api/quick-action/txt-to-xml-config"
import { cn } from "@/lib/utils"

const listHref = "/dashboard/xml-apis/bank-api"

type BankApiTxtToXmlFormProps = {
  bankId: string
  bankName: string
  action?: BankApiQuickActionTxtToXmlDefinition
  onShowBulkView?: () => void
}

type PrefixFiles = Record<string, File | null>

function createEmptyPrefixFiles(prefixes: readonly string[]): PrefixFiles {
  return prefixes.reduce((accumulator, prefix) => {
    accumulator[prefix] = null
    return accumulator
  }, {} as PrefixFiles)
}

export function BankApiTxtToXmlForm({ bankId, bankName, onShowBulkView }: BankApiTxtToXmlFormProps) {
  const [outputType, setOutputType] = React.useState<UbsTxtXmlOutputType>("position")
  const [prefixFiles, setPrefixFiles] = React.useState<PrefixFiles>(() =>
    createEmptyPrefixFiles(getUbsTxtXmlPrefixes("position"))
  )
  const [fileError, setFileError] = React.useState<string | null>(null)
  const [isSubmitting, setIsSubmitting] = React.useState(false)

  const activePrefixes = getUbsTxtXmlPrefixes(outputType)
  const selectedOutput = getUbsTxtXmlOutputOption(outputType)
  const otherOutputs = UBS_TXT_XML_OUTPUT_OPTIONS.filter((option) => option.id !== outputType)
  const uploadedFiles = activePrefixes
    .map((prefix) => prefixFiles[prefix])
    .filter((file): file is File => file instanceof File)

  const handleOutputTypeChange = (nextType: UbsTxtXmlOutputType) => {
    setOutputType(nextType)
    setPrefixFiles(createEmptyPrefixFiles(getUbsTxtXmlPrefixes(nextType)))
    setFileError(null)
  }

  const handlePrefixFileChange = (prefix: string, file: File | null) => {
    setPrefixFiles((current) => ({ ...current, [prefix]: file }))
    setFileError(null)
  }

  const handleReset = () => {
    setOutputType("position")
    setPrefixFiles(createEmptyPrefixFiles(getUbsTxtXmlPrefixes("position")))
    setFileError(null)
  }

  const handleSubmit = async () => {
    if (!uploadedFiles.length) {
      setFileError("Upload at least one TXT file")
      return
    }

    setIsSubmitting(true)
    try {
      await submitBankApiTxtToXml({
        bankId,
        bankName,
        outputType,
        files: uploadedFiles,
      })
      toast.success(`${selectedOutput.downloadLabel} completed`)
    } catch (error) {
      toastApiError(error, "Failed to convert TXT to XML")
    } finally {
      setIsSubmitting(false)
    }
  }

  return (
    <div className="pb-4">
      <FormPageHeader
        backHref={listHref}
        breadcrumb={[
          { label: "XML API" },
          { label: "Bank Api", href: listHref },
          { label: "TXT to XML" },
        ]}
        titleIcon={<FileCode2 className="size-5 text-primary" />}
        title="TXT to XML Converter"
        description={`${bankName} — Upload TXT files and generate XML output.`}
        meta={
          <div className="flex flex-wrap items-center gap-2">
            {onShowBulkView ? (
              <Button type="button" variant="outline" size="sm" className="gap-1.5" onClick={onShowBulkView}>
                <Archive className="size-4" />
                Bulk TXT → merged POS + TRX (ZIP)
              </Button>
            ) : null}
            <Button type="button" variant="outline" size="sm" className="gap-1.5" asChild>
              <Link href={listHref}>
                <X className="size-4" />
                Cancel
              </Link>
            </Button>
          </div>
        }
      />

      <div className="space-y-6">
        <FormPanel title="Xml Output">
          <Field className="gap-2">
            <FieldLabel className="text-sm font-medium">
              Xml Output <span className="text-destructive">*</span>
            </FieldLabel>
            <div className="flex flex-wrap items-center gap-x-2 gap-y-1 text-sm">
              <span className="font-semibold">{selectedOutput.generateLabel}</span>
              {otherOutputs.map((option) => (
                <span key={option.id} className="inline-flex items-center gap-2">
                  <span className="text-muted-foreground">|</span>
                  <button
                    type="button"
                    className="text-primary hover:underline"
                    onClick={() => handleOutputTypeChange(option.id)}
                  >
                    {option.switchLabel}
                  </button>
                </span>
              ))}
            </div>
            <p className="text-xs text-muted-foreground">Upload a TXT file.</p>
          </Field>
        </FormPanel>

        <FormPanel
          title={`Upload TXT Files ${bankId}`}
          description={`Supported prefixes: ${activePrefixes.join(", ")}`}
        >
          <div className="space-y-4">
            {activePrefixes.map((prefix) => {
              const selectedFile = prefixFiles[prefix]
              const inputId = `txt-file-${bankId}-${outputType}-${prefix}`

              return (
                <div
                  key={prefix}
                  className="grid gap-3 rounded-lg border bg-muted/20 p-4 sm:grid-cols-[72px_minmax(0,1fr)_auto] sm:items-center"
                >
                  <Label htmlFor={inputId} className="font-semibold text-sm">
                    {prefix}
                  </Label>
                  <div className="space-y-1">
                    <Input
                      id={inputId}
                      type="file"
                      accept=".txt,text/plain"
                      className="h-9 cursor-pointer file:mr-3 file:rounded-md file:border-0 file:bg-muted file:px-3 file:py-1 file:text-xs file:font-medium"
                      onChange={(event) => {
                        const file = event.target.files?.[0] ?? null
                        handlePrefixFileChange(prefix, file)
                      }}
                    />
                    <p className="truncate text-xs text-muted-foreground">
                      {selectedFile?.name ?? "No file chosen"}
                    </p>
                  </div>
                  <Button
                    type="button"
                    variant="outline"
                    size="sm"
                    className={cn(
                      "gap-1.5 border-destructive/30 text-destructive hover:bg-destructive/10 hover:text-destructive",
                      !selectedFile && "invisible sm:visible sm:opacity-40"
                    )}
                    disabled={!selectedFile || isSubmitting}
                    onClick={() => {
                      handlePrefixFileChange(prefix, null)
                      const input = document.getElementById(inputId) as HTMLInputElement | null
                      if (input) input.value = ""
                    }}
                  >
                    <Trash2 className="size-4" />
                    Remove
                  </Button>
                </div>
              )
            })}

            <p className="text-xs text-muted-foreground">
              Upload TXT files. The system will automatically detect prefixes ({activePrefixes.join(", ")})
              from filenames. Each prefix has its own upload field.
            </p>

            <FieldError errors={fileError ? [{ message: fileError }] : undefined} />
          </div>
        </FormPanel>
      </div>

      <div className="sticky bottom-0 z-10 -mx-4 mt-6 flex flex-wrap items-center justify-end gap-2 border-t bg-background/95 px-4 py-3 backdrop-blur supports-[backdrop-filter]:bg-background/80 md:-mx-6 md:px-6">
        <Button
          type="button"
          variant="ghost"
          size="sm"
          onClick={handleReset}
          disabled={isSubmitting}
        >
          Reset
        </Button>
        <Button
          type="button"
          size="sm"
          className="min-w-[200px] gap-1.5"
          disabled={isSubmitting}
          onClick={() => void handleSubmit()}
        >
          {isSubmitting ? (
            <>
              <Loader2 className="size-4 animate-spin" />
              Converting…
            </>
          ) : (
            <>
              <FileCode2 className="size-4" />
              {selectedOutput.downloadLabel}
            </>
          )}
        </Button>
      </div>
    </div>
  )
}
