import { useCallback, useEffect, useMemo, useState } from "react";
import { Link, useParams } from "react-router-dom";
import { format } from "date-fns";
import { AlertCircle, CheckCircle, ExternalLink, Loader2, Upload, X } from "lucide-react";
import { useDropzone } from "react-dropzone";
import { supabase } from "@/integrations/supabase/client";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { Switch } from "@/components/ui/switch";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Separator } from "@/components/ui/separator";
import PublicFormSignatureField from "@/components/forms/PublicFormSignatureField";
import ContentBlocksRenderer from "@/components/public-content/ContentBlocksRenderer";

function normalizeOptions(options) {
  if (Array.isArray(options)) return options.filter(Boolean).map((option) => String(option).trim()).filter(Boolean);
  if (typeof options === "string") return options.split(",").map((option) => option.trim()).filter(Boolean);
  return [];
}

function isStaticField(fieldType) {
  return ["header", "paragraph", "spacer", "divider", "horizontal_line"].includes(fieldType);
}

function SubmissionFileField({ value = [], onChange, maxFiles = 5 }) {
  const files = Array.isArray(value) ? value : [];

  const handleDrop = useCallback(
    (acceptedFiles) => {
      onChange?.([...files, ...acceptedFiles].slice(0, maxFiles));
    },
    [files, maxFiles, onChange]
  );

  const { getRootProps, getInputProps, isDragActive } = useDropzone({
    onDrop: handleDrop,
    maxFiles,
    maxSize: 25 * 1024 * 1024,
  });

  const removeFile = (index) => {
    onChange?.(files.filter((_, fileIndex) => fileIndex !== index));
  };

  return (
    <div className="space-y-3">
      <div
        {...getRootProps()}
        className={`rounded-lg border-2 border-dashed p-5 text-center transition-colors ${
          isDragActive ? "border-primary bg-primary/5" : "border-border bg-muted/20 hover:border-primary/50"
        }`}
      >
        <input {...getInputProps()} />
        <Upload className="mx-auto mb-2 h-5 w-5 text-muted-foreground" />
        <p className="text-sm text-foreground">{isDragActive ? "Drop files here" : "Drag files here or click to browse"}</p>
        <p className="mt-1 text-xs text-muted-foreground">Up to {maxFiles} files • 25MB max each</p>
      </div>

      {files.length > 0 && (
        <div className="space-y-2">
          {files.map((file, index) => (
            <div key={`${file.name}-${index}`} className="flex items-center justify-between gap-3 rounded-md border border-border bg-muted/30 px-3 py-2 text-sm">
              <div className="min-w-0 flex-1">
                <p className="truncate font-medium text-foreground">{file.name}</p>
                <p className="text-xs text-muted-foreground">{Math.max(1, Math.round(file.size / 1024))} KB</p>
              </div>
              <Button type="button" variant="ghost" size="icon" className="h-8 w-8" onClick={() => removeFile(index)}>
                <X className="h-4 w-4" />
              </Button>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

function renderStaticField(field) {
  if (field.type === "header") {
    return <h2 className="text-2xl font-semibold text-foreground">{field.label || "Section heading"}</h2>;
  }

  if (field.type === "paragraph") {
    return <p className="whitespace-pre-wrap text-sm leading-6 text-muted-foreground">{field.label || "Instructions"}</p>;
  }

  if (field.type === "spacer") {
    return <div style={{ height: field.style?.height || "32px" }} aria-hidden="true" />;
  }

  return <Separator className="my-2" />;
}

export default function PublicFormSubmitPage() {
  const { slug } = useParams();
  const [template, setTemplate] = useState(null);
  const [loading, setLoading] = useState(true);
  const [submitting, setSubmitting] = useState(false);
  const [submitted, setSubmitted] = useState(false);
  const [error, setError] = useState("");
  const [formValues, setFormValues] = useState({});
  const [attachments, setAttachments] = useState([]);
  const [submitterName, setSubmitterName] = useState("");
  const [submitterEmail, setSubmitterEmail] = useState("");
  const [requiresLogin, setRequiresLogin] = useState(false);

  useEffect(() => {
    const fetchTemplate = async () => {
      setLoading(true);
      setError("");

      try {
        const [{ data, error: templateError }, { data: authData, error: authError }] = await Promise.all([
          supabase
            .from("public_form_templates")
            .select("*")
            .eq("slug", slug)
            .eq("is_published", true)
            .maybeSingle(),
          supabase.auth.getUser(),
        ]);

        if (templateError) throw templateError;
        if (authError) throw authError;
        if (!data) {
          setError("This public form could not be found.");
          return;
        }

        setTemplate(data);
        if (data.require_auth && !authData.user) {
          setRequiresLogin(true);
        }
      } catch (fetchError) {
        setError(fetchError.message || "Failed to load form.");
      } finally {
        setLoading(false);
      }
    };

    fetchTemplate();
  }, [slug]);

  const fields = useMemo(() => (Array.isArray(template?.fields) ? template.fields : []), [template?.fields]);
  const dynamicFields = useMemo(() => fields.filter((field) => !isStaticField(field.type)), [fields]);

  const setFieldValue = (fieldId, value) => {
    setFormValues((previous) => ({ ...previous, [fieldId]: value }));
  };

  const uploadFiles = async (files, fieldId) => {
    if (!files?.length || !template?.id) return [];

    const uploads = await Promise.all(
      files.map(async (file) => {
        const fileName = file.name.replace(/[^a-zA-Z0-9._-]/g, "_");
        const path = `${template.id}/${fieldId}/${Date.now()}-${crypto.randomUUID()}-${fileName}`;
        const { error: uploadError } = await supabase.storage.from("public-form-attachments").upload(path, file);
        if (uploadError) throw uploadError;

        const { data: publicUrlData } = supabase.storage.from("public-form-attachments").getPublicUrl(path);
        return {
          name: file.name,
          url: publicUrlData.publicUrl,
          size: file.size,
          type: file.type || null,
          path,
        };
      })
    );

    return uploads;
  };

  const validateSubmission = () => {
    if (requiresLogin) return "Please sign in to submit this form.";

    for (const field of dynamicFields) {
      if (!field.required) continue;

      const value = formValues[field.id];
      if (field.type === "checkbox" || field.type === "toggle") {
        if (!value) return `${field.label || "This field"} is required.`;
        continue;
      }

      if (field.type === "file") {
        if (!Array.isArray(value) || value.length === 0) return `${field.label || "This field"} is required.`;
        continue;
      }

      if (field.type === "signature") {
        if (!value) return `${field.label || "Signature"} is required.`;
        continue;
      }

      if (value === undefined || value === null || value === "") {
        return `${field.label || "This field"} is required.`;
      }
    }

    return "";
  };

  const handleSubmit = async (event) => {
    event.preventDefault();
    if (!template) return;

    const validationError = validateSubmission();
    if (validationError) {
      setError(validationError);
      return;
    }

    setSubmitting(true);
    setError("");

    try {
      const submissionValues = {};

      for (const field of dynamicFields) {
        const rawValue = formValues[field.id];

        if (field.type === "file") {
          submissionValues[field.id] = await uploadFiles(Array.isArray(rawValue) ? rawValue : [], field.id);
          continue;
        }

        submissionValues[field.id] = rawValue ?? null;
      }

      const uploadedAttachments = template.allow_attachments ? await uploadFiles(attachments, "additional-attachments") : [];

      const payload = {
        template_id: template.id,
        association_id: template.association_id,
        submitter_name: submitterName.trim() || null,
        submitter_email: submitterEmail.trim() || null,
        form_data: {
          values: submissionValues,
          fields_snapshot: fields,
          metadata: {
            slug,
            submitted_at: new Date().toISOString(),
            template_title: template.title,
          },
        },
        attachments: uploadedAttachments,
        status: "pending",
      };

      const { error: insertError } = await supabase.from("public_form_submissions").insert(payload);
      if (insertError) throw insertError;

      setSubmitted(true);
      setFormValues({});
      setAttachments([]);
    } catch (submitError) {
      setError(submitError.message || "Submission failed.");
    } finally {
      setSubmitting(false);
    }
  };

  if (loading) {
    return (
      <div className="flex min-h-screen items-center justify-center bg-background">
        <Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
      </div>
    );
  }

  if (!template) {
    return (
      <div className="flex min-h-screen items-center justify-center bg-background px-4">
        <Card className="w-full max-w-lg">
          <CardContent className="pt-6 text-center">
            <AlertCircle className="mx-auto mb-3 h-10 w-10 text-destructive" />
            <p className="text-sm text-muted-foreground">{error || "This public form is unavailable."}</p>
          </CardContent>
        </Card>
      </div>
    );
  }

  if (requiresLogin) {
    return (
      <div className="flex min-h-screen items-center justify-center bg-background px-4 py-10">
        <Card className="w-full max-w-lg">
          <CardHeader>
            <CardTitle>Sign in required</CardTitle>
          </CardHeader>
          <CardContent className="space-y-4">
            <p className="text-sm text-muted-foreground">This form can only be submitted by signed-in users.</p>
            <Button asChild className="w-full">
              <Link to="/auth">Go to sign in</Link>
            </Button>
          </CardContent>
        </Card>
      </div>
    );
  }

  if (submitted) {
    return (
      <div className="flex min-h-screen items-center justify-center bg-background px-4 py-10">
        <Card className="w-full max-w-lg">
          <CardContent className="space-y-4 pt-6 text-center">
            <CheckCircle className="mx-auto h-12 w-12 text-primary" />
            <div>
              <h2 className="text-xl font-semibold text-foreground">Submission received</h2>
              <p className="mt-1 text-sm text-muted-foreground">Thank you — your form was submitted successfully.</p>
            </div>
          </CardContent>
        </Card>
      </div>
    );
  }

  const sidebarEnabled = Boolean(template.sidebar_enabled) && Array.isArray(template.sidebar_blocks) && template.sidebar_blocks.length > 0;
  const hasBodyBlocks = Array.isArray(template.body_blocks) && template.body_blocks.length > 0;

  return (
    <div className="min-h-screen bg-background px-4 py-8">
      <form onSubmit={handleSubmit} className={`mx-auto ${sidebarEnabled ? "max-w-5xl" : "max-w-3xl"} space-y-6`}>
        <div className={sidebarEnabled ? "grid gap-6 lg:grid-cols-[1fr_280px]" : ""}>
          <div className="space-y-6 min-w-0">
        <Card className="overflow-hidden">
          {(template.settings?.logoUrl || template.settings?.organizationName) && (
            <div className="border-b border-border bg-muted/30 px-6 py-4">
              <div className="flex items-center gap-4">
                {template.settings?.logoUrl ? (
                  <img src={template.settings.logoUrl} alt={template.settings.organizationName || template.title} className="h-12 w-12 rounded-md border border-border object-cover" />
                ) : null}
                <div>
                  {template.settings?.organizationName ? (
                    <p className="text-sm font-medium text-foreground">{template.settings.organizationName}</p>
                  ) : null}
                  <p className="text-xs text-muted-foreground">Shared form</p>
                </div>
              </div>
            </div>
          )}

          <CardHeader className="space-y-2">
            <CardTitle className="text-2xl">{template.title}</CardTitle>
            {template.description ? <p className="text-sm text-muted-foreground">{template.description}</p> : null}
          </CardHeader>

          <CardContent className="space-y-6">
            {hasBodyBlocks ? (
              <div className="space-y-4 rounded-lg bg-muted/20 p-4">
                <ContentBlocksRenderer blocks={template.body_blocks} variant="main" />
              </div>
            ) : null}
            <div className="grid gap-4 md:grid-cols-2">
              <div className="space-y-2">
                <Label htmlFor="submitter_name">Contact name</Label>
                <Input
                  id="submitter_name"
                  value={submitterName}
                  onChange={(event) => setSubmitterName(event.target.value)}
                  placeholder="Your full name"
                />
              </div>
              <div className="space-y-2">
                <Label htmlFor="submitter_email">Contact email</Label>
                <Input
                  id="submitter_email"
                  type="email"
                  value={submitterEmail}
                  onChange={(event) => setSubmitterEmail(event.target.value)}
                  placeholder="you@example.com"
                />
              </div>
            </div>

            <Separator />

            <div className="space-y-6">
              {fields.map((field) => {
                if (isStaticField(field.type)) {
                  return <div key={field.id || field.label}>{renderStaticField(field)}</div>;
                }

                const value = formValues[field.id];
                const options = normalizeOptions(field.options);

                return (
                  <div key={field.id} className="space-y-2">
                    <div className="space-y-1">
                      <Label className="text-sm font-medium text-foreground">
                        {field.label || "Untitled field"}
                        {field.required ? <span className="ml-1 text-destructive">*</span> : null}
                      </Label>
                      {field.helpText ? <p className="text-xs text-muted-foreground">{field.helpText}</p> : null}
                    </div>

                    {["text", "email", "name", "number"].includes(field.type) ? (
                      <Input
                        type={field.type === "number" ? "number" : field.type === "email" ? "email" : "text"}
                        value={value || ""}
                        onChange={(event) => setFieldValue(field.id, event.target.value)}
                        placeholder={field.placeholder || ""}
                      />
                    ) : null}

                    {field.type === "textarea" ? (
                      <Textarea
                        value={value || ""}
                        onChange={(event) => setFieldValue(field.id, event.target.value)}
                        placeholder={field.placeholder || ""}
                        className="min-h-[120px]"
                      />
                    ) : null}

                    {field.type === "date" ? (
                      <Input type="date" value={value || ""} onChange={(event) => setFieldValue(field.id, event.target.value)} />
                    ) : null}

                    {field.type === "time" ? (
                      <Input type="time" value={value || ""} onChange={(event) => setFieldValue(field.id, event.target.value)} />
                    ) : null}

                    {field.type === "select" ? (
                      <Select value={value || ""} onValueChange={(nextValue) => setFieldValue(field.id, nextValue)}>
                        <SelectTrigger>
                          <SelectValue placeholder={field.placeholder || "Select an option"} />
                        </SelectTrigger>
                        <SelectContent>
                          {options.map((option) => (
                            <SelectItem key={option} value={option}>
                              {option}
                            </SelectItem>
                          ))}
                        </SelectContent>
                      </Select>
                    ) : null}

                    {field.type === "checkbox" ? (
                      <label className="flex items-center gap-3 rounded-md border border-border bg-muted/20 px-3 py-3 text-sm">
                        <input
                          type="checkbox"
                          checked={Boolean(value)}
                          onChange={(event) => setFieldValue(field.id, event.target.checked)}
                          className="h-4 w-4"
                        />
                        <span>{field.placeholder || field.label || "Checkbox"}</span>
                      </label>
                    ) : null}

                    {field.type === "toggle" ? (
                      <div className="flex items-center justify-between rounded-md border border-border bg-muted/20 px-3 py-3">
                        <span className="text-sm text-foreground">{field.placeholder || "Toggle selection"}</span>
                        <Switch checked={Boolean(value)} onCheckedChange={(nextValue) => setFieldValue(field.id, nextValue)} />
                      </div>
                    ) : null}

                    {field.type === "file" ? <SubmissionFileField value={value} onChange={(nextValue) => setFieldValue(field.id, nextValue)} /> : null}

                    {field.type === "signature" ? <PublicFormSignatureField value={value || ""} onChange={(nextValue) => setFieldValue(field.id, nextValue)} /> : null}
                  </div>
                );
              })}
            </div>

            {template.allow_attachments ? (
              <>
                <Separator />
                <div className="space-y-2">
                  <Label>Additional attachments</Label>
                  <SubmissionFileField value={attachments} onChange={setAttachments} />
                </div>
              </>
            ) : null}

            {error ? (
              <div className="rounded-md border border-destructive/20 bg-destructive/10 px-3 py-2 text-sm text-destructive">
                {error}
              </div>
            ) : null}

            <div className="flex flex-col gap-3 border-t border-border pt-4 sm:flex-row sm:items-center sm:justify-between">
              <p className="text-xs text-muted-foreground">
                Shared on {format(new Date(), "PPP")}
              </p>
              <Button type="submit" disabled={submitting} className="sm:min-w-[180px]">
                {submitting ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : null}
                Submit form
              </Button>
            </div>
          </CardContent>
        </Card>
          </div>

          {sidebarEnabled ? (
            <aside className="lg:sticky lg:top-6 lg:self-start">
              <Card className="overflow-hidden">
                <CardContent className="space-y-3 pt-5">
                  {template.sidebar_title ? (
                    <h3 className="text-base font-semibold text-foreground">{template.sidebar_title}</h3>
                  ) : null}
                  <ContentBlocksRenderer blocks={template.sidebar_blocks} variant="sidebar" />
                </CardContent>
              </Card>
            </aside>
          ) : null}
        </div>
      </form>
    </div>
  );
}
