import SaveIcon from "@mui/icons-material/Save";
import {
  Box,
  Button,
  FormControlLabel,
  Grid,
  Paper,
  Stack,
  Switch,
  TextField,
  Typography
} from "@mui/material";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { zodResolver } from "@hookform/resolvers/zod";
import { Controller, useForm } from "react-hook-form";
import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { useNavigate, useParams } from "react-router-dom";
import { z } from "zod";

import {
  createContract,
  fetchContract,
  fetchPaperlessDocument,
  updateContract
} from "../api/contracts";
import { fetchServerConfig } from "../api/config";
import PaperlessSearchDialog from "../components/PaperlessSearchDialog";
import PageHeader from "../components/PageHeader";
import { useSnackbar } from "../hooks/useSnackbar";
import { ContractPayload, PaperlessDocument } from "../types";

const formSchema = z.object({
  title: z.string().min(1, "Titel erforderlich"),
  provider: z.string().optional(),
  category: z.string().optional(),
  paperlessDocumentId: z.string().optional(),
  contractStartDate: z.string().optional(),
  contractEndDate: z.string().optional(),
  terminationNoticeDays: z.string().optional(),
  renewalPeriodMonths: z.string().optional(),
  autoRenew: z.boolean().optional(),
  price: z.string().optional(),
  currency: z.string().optional(),
  notes: z.string().optional(),
  tags: z.string().optional()
});

type FormValues = z.infer<typeof formSchema>;

interface Props {
  mode: "create" | "edit";
}

function parseInteger(input?: string | null): number | null {
  if (!input) return null;
  const value = Number(input);
  if (!Number.isFinite(value)) {
    throw new Error("Invalid number");
  }
  return Math.round(value);
}

function parseDecimal(input?: string | null): number | null {
  if (!input) return null;
  const normalized = input.replace(",", ".").trim();
  const value = Number(normalized);
  if (!Number.isFinite(value)) {
    throw new Error("Invalid number");
  }
  return value;
}

function parseTags(input?: string | null): string[] {
  if (!input) return [];
  return input
    .split(",")
    .map((tag) => tag.trim())
    .filter(Boolean);
}

export default function ContractForm({ mode }: Props) {
  const navigate = useNavigate();
  const { contractId } = useParams<{ contractId: string }>();
  const id = contractId ? Number(contractId) : null;
  const queryClient = useQueryClient();
  const { showMessage } = useSnackbar();
  const { t } = useTranslation();

  const {
    control,
    register,
    handleSubmit,
    formState: { errors },
    reset,
    setValue,
    watch
  } = useForm<FormValues>({
    resolver: zodResolver(formSchema),
    defaultValues: {
      title: "",
      provider: "",
      category: "",
      contractStartDate: "",
      contractEndDate: "",
      terminationNoticeDays: "",
      renewalPeriodMonths: "",
      autoRenew: false,
      price: "",
      currency: "EUR",
      notes: "",
      tags: ""
    }
  });

  const { data: contract, isLoading } = useQuery({
    queryKey: ["contracts", id],
    queryFn: () => fetchContract(id ?? 0),
    enabled: mode === "edit" && id !== null
  });

  const { data: serverConfig } = useQuery({
    queryKey: ["server-config"],
    queryFn: fetchServerConfig
  });

  const { data: linkedPaperlessDoc } = useQuery({
    queryKey: ["contracts", id, "paperless"],
    queryFn: () => fetchPaperlessDocument(id ?? 0),
    enabled: mode === "edit" && id !== null
  });

  const [searchDialogOpen, setSearchDialogOpen] = useState(false);
  const [selectedDocument, setSelectedDocument] = useState<PaperlessDocument | null>(null);
  const paperlessDocumentId = watch("paperlessDocumentId");

  useEffect(() => {
    if (mode === "edit" && contract) {
      reset({
        title: contract.title,
        provider: contract.provider ?? "",
        category: contract.category ?? "",
        contractStartDate: contract.contractStartDate ?? "",
        contractEndDate: contract.contractEndDate ?? "",
        terminationNoticeDays: contract.terminationNoticeDays
          ? String(contract.terminationNoticeDays)
          : "",
        renewalPeriodMonths: contract.renewalPeriodMonths
          ? String(contract.renewalPeriodMonths)
          : "",
        autoRenew: contract.autoRenew ?? false,
        price: contract.price ? String(contract.price) : "",
        currency: contract.currency ?? "EUR",
        notes: contract.notes ?? "",
        paperlessDocumentId: contract.paperlessDocumentId
          ? String(contract.paperlessDocumentId)
          : "",
        tags: contract.tags?.join(", ") ?? ""
      });
    }
  }, [contract, mode, reset]);

  useEffect(() => {
    if (linkedPaperlessDoc) {
      setSelectedDocument(linkedPaperlessDoc);
    }
  }, [linkedPaperlessDoc]);

  useEffect(() => {
    if (!paperlessDocumentId) {
      setSelectedDocument(null);
      return;
    }
    if (selectedDocument?.id && String(selectedDocument.id) === paperlessDocumentId) {
      return;
    }
    if (selectedDocument && String(selectedDocument.id ?? "") !== paperlessDocumentId) {
      setSelectedDocument(null);
    }
  }, [paperlessDocumentId, selectedDocument]);

  const mutation = useMutation({
    mutationFn: async (values: FormValues) => {
      const payload: ContractPayload = {
        title: values.title,
        provider: values.provider?.trim() || null,
        category: values.category?.trim() || null,
        contractStartDate: values.contractStartDate || null,
        contractEndDate: values.contractEndDate || null,
        terminationNoticeDays: parseInteger(values.terminationNoticeDays ?? undefined),
        renewalPeriodMonths: parseInteger(values.renewalPeriodMonths ?? undefined),
        autoRenew: values.autoRenew ?? false,
        price: parseDecimal(values.price ?? undefined),
        currency: values.currency?.trim() || "EUR",
        notes: values.notes?.trim() || null,
        paperlessDocumentId: parseInteger(values.paperlessDocumentId ?? undefined),
        tags: parseTags(values.tags ?? "")
      };

      if (mode === "create") {
        return createContract(payload);
      }
      if (!id) {
        throw new Error("Invalid contract ID");
      }
      return updateContract(id, payload);
    },
    onSuccess: (updated) => {
      queryClient.invalidateQueries({ queryKey: ["contracts"] });
      showMessage(t("contractForm.saved", { title: updated.title }), "success");
      navigate(`/contracts/${updated.id}`);
    },
    onError: (error: Error) => {
      const message = error.message === "Invalid number" ? t("contractForm.invalidNumber") : error.message ?? t("contractForm.saveError");
      showMessage(message, "error");
    }
  });

  if (mode === "edit" && (isLoading || !contract)) {
    return <Typography>{t("contractForm.loading")}</Typography>;
  }

  return (
    <>
      <PageHeader
        title={mode === "create" ? t("contractForm.createTitle") : t("contractDetail.edit")}
        subtitle={
          mode === "create"
            ? t("contractForm.createSubtitle")
            : t("contractForm.editSubtitle", { title: contract?.title ?? "" })
        }
      />

      <Paper variant="outlined" sx={{ p: 3, borderRadius: 3 }}>
        <Box
          component="form"
          onSubmit={handleSubmit((values) => mutation.mutate(values))}
          noValidate
        >
          <Grid container spacing={2}>
            <Grid item xs={12} md={6}>
              <TextField
                label={t("contractForm.fields.title")}
                fullWidth
                required
                {...register("title")}
                error={Boolean(errors.title)}
                helperText={errors.title?.message}
              />
            </Grid>
            <Grid item xs={12} md={6}>
              <TextField label={t("contractForm.fields.provider")} fullWidth {...register("provider")} />
            </Grid>
            <Grid item xs={12} md={6}>
              <TextField label={t("contractForm.fields.category")} fullWidth {...register("category")} />
            </Grid>
            <Grid item xs={12} md={6}>
              <Stack direction={{ xs: "column", sm: "row" }} spacing={1} alignItems="flex-start">
                <TextField
                  label={t("contractForm.fields.paperlessId")}
                  fullWidth
                  {...register("paperlessDocumentId")}
                  error={Boolean(errors.paperlessDocumentId)}
                  helperText={errors.paperlessDocumentId?.message}
                />
                <Button
                  variant="outlined"
                  onClick={() => setSearchDialogOpen(true)}
                  disabled={!serverConfig?.paperlessConfigured}
                >
                  {t("contractForm.fields.searchButton")}
                </Button>
              </Stack>
              {!serverConfig?.paperlessConfigured && (
                <Typography variant="caption" color="text.secondary">
                  {t("contractForm.paperlessNotConfigured")}
                </Typography>
              )}
              {selectedDocument && (
                <Typography variant="caption" color="text.secondary" sx={{ display: "block", mt: 1 }}>
                  {t("contractForm.paperlessLinked", {
                    title: selectedDocument.title ?? `#${selectedDocument.id}`
                  })}
                </Typography>
              )}
            </Grid>
            <Grid item xs={12} md={6}>
              <TextField
                label={t("contractForm.fields.contractStart")}
                type="date"
                fullWidth
                InputLabelProps={{ shrink: true }}
                {...register("contractStartDate")}
              />
            </Grid>
            <Grid item xs={12} md={6}>
              <TextField
                label={t("contractForm.fields.contractEnd")}
                type="date"
                fullWidth
                InputLabelProps={{ shrink: true }}
                {...register("contractEndDate")}
              />
            </Grid>
            <Grid item xs={12} md={4}>
              <TextField
                label={t("contractForm.fields.terminationNotice")}
                fullWidth
                {...register("terminationNoticeDays")}
                error={Boolean(errors.terminationNoticeDays)}
                helperText={errors.terminationNoticeDays?.message}
              />
            </Grid>
            <Grid item xs={12} md={4}>
              <TextField
                label={t("contractForm.fields.renewalPeriod")}
                fullWidth
                {...register("renewalPeriodMonths")}
                error={Boolean(errors.renewalPeriodMonths)}
                helperText={errors.renewalPeriodMonths?.message}
              />
            </Grid>
            <Grid item xs={12} md={4}>
              <Controller
                control={control}
                name="autoRenew"
                render={({ field }) => (
                  <FormControlLabel
                    label={t("contractForm.fields.autoRenew")}
                    control={
                      <Switch
                        checked={field.value ?? false}
                        onChange={(event) => field.onChange(event.target.checked)}
                      />
                    }
                  />
                )}
              />
            </Grid>
            <Grid item xs={12} md={4}>
              <TextField
                label={t("contractForm.fields.price")}
                fullWidth
                {...register("price")}
                error={Boolean(errors.price)}
                helperText={errors.price?.message}
              />
            </Grid>
            <Grid item xs={12} md={4}>
              <TextField
                label={t("contractForm.fields.currency")}
                fullWidth
                {...register("currency")}
                error={Boolean(errors.currency)}
                helperText={errors.currency?.message}
              />
            </Grid>
            <Grid item xs={12}>
              <TextField
                label={t("contractForm.fields.notes")}
                fullWidth
                multiline
                minRows={3}
                {...register("notes")}
              />
            </Grid>
            <Grid item xs={12}>
              <TextField
                label={t("contractForm.fields.tags")}
                fullWidth
                placeholder={t("contractForm.tagsPlaceholder")}
                {...register("tags")}
              />
            </Grid>
          </Grid>

          <Box display="flex" justifyContent="flex-end" mt={4}>
            <Button
              type="submit"
              variant="contained"
              startIcon={<SaveIcon />}
              disabled={mutation.isPending}
            >
              {mutation.isPending ? "Speichere..." : "Speichern"}
            </Button>
          </Box>
        </Box>
      </Paper>

      <PaperlessSearchDialog
        open={searchDialogOpen}
        onClose={() => setSearchDialogOpen(false)}
        onSelect={(doc) => {
          const idValue = doc.id ? String(doc.id) : "";
          setValue("paperlessDocumentId", idValue, { shouldDirty: true });
          setSelectedDocument(doc);
        }}
      />
    </>
  );
}
