import { Head, Link, useForm } from '@inertiajs/react';
import { useMemo, useState } from 'react';
import { ConflictCheckWidget } from '@/components/conflict-check-widget';
import InputError from '@/components/input-error';
import { PageHeader } from '@/components/page-header';
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 {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import { Spinner } from '@/components/ui/spinner';
import { index, show, store, update } from '@/routes/clients';

type Option = { value: number | string; label: string };

type Client = {
    id: string;
    client_number: string;
    status: string;
    relationship_partner_id: number | null;
    contact_name: string;
};

const NONE = 'none';

export default function ClientForm({
    client,
    contacts,
    partners,
    statuses,
}: {
    client: Client | null;
    contacts: Option[];
    partners: Option[];
    statuses: Option[];
}) {
    const editing = client !== null;
    const [mode, setMode] = useState<'new' | 'existing'>('new');

    const form = useForm({
        contact_id: null as number | null,
        contact: {
            kind: 'organization',
            name: '',
            email: '',
            phone: '',
            rc_number: '',
        },
        relationship_partner_id: client?.relationship_partner_id ?? null,
        status: client?.status ?? 'active',
    });

    const checkName = useMemo(() => {
        if (editing) {
            return client!.contact_name;
        }

        if (mode === 'new') {
            return form.data.contact.name;
        }

        const selected = contacts.find((c) => c.value === form.data.contact_id);

        return selected?.label ?? '';
    }, [
        editing,
        client,
        mode,
        form.data.contact.name,
        form.data.contact_id,
        contacts,
    ]);

    const submit = (e: React.FormEvent) => {
        e.preventDefault();

        if (editing) {
            form.transform((d) => ({
                status: d.status,
                relationship_partner_id: d.relationship_partner_id,
            }));
            form.put(update(client.id).url, { preserveScroll: true });

            return;
        }

        form.transform((d) =>
            mode === 'new'
                ? {
                      contact: d.contact,
                      relationship_partner_id: d.relationship_partner_id,
                      status: d.status,
                  }
                : {
                      contact_id: d.contact_id,
                      relationship_partner_id: d.relationship_partner_id,
                      status: d.status,
                  },
        );
        form.post(store().url, { preserveScroll: true });
    };

    return (
        <>
            <Head title={editing ? 'Edit client' : 'New client'} />
            <form onSubmit={submit} className="flex flex-col gap-6 p-4">
                <PageHeader
                    title={
                        editing ? `Edit ${client!.client_number}` : 'New client'
                    }
                    subtitle={
                        editing
                            ? client!.contact_name
                            : 'Onboard a new client and run a conflict check.'
                    }
                    action={
                        <div className="flex gap-2">
                            <Button asChild variant="outline" type="button">
                                <Link
                                    href={editing ? show(client!.id) : index()}
                                >
                                    Cancel
                                </Link>
                            </Button>
                            <Button type="submit" disabled={form.processing}>
                                {form.processing && <Spinner />}
                                Save
                            </Button>
                        </div>
                    }
                />

                <div className="grid gap-6 lg:grid-cols-3">
                    <div className="flex flex-col gap-6 lg:col-span-2">
                        {!editing && (
                            <Card>
                                <CardHeader>
                                    <CardTitle>Contact</CardTitle>
                                </CardHeader>
                                <CardContent className="space-y-4">
                                    <div className="flex gap-2">
                                        <Button
                                            type="button"
                                            variant={
                                                mode === 'new'
                                                    ? 'default'
                                                    : 'outline'
                                            }
                                            size="sm"
                                            onClick={() => setMode('new')}
                                        >
                                            New contact
                                        </Button>
                                        <Button
                                            type="button"
                                            variant={
                                                mode === 'existing'
                                                    ? 'default'
                                                    : 'outline'
                                            }
                                            size="sm"
                                            onClick={() => setMode('existing')}
                                        >
                                            Existing contact
                                        </Button>
                                    </div>

                                    {mode === 'existing' ? (
                                        <div className="grid gap-2">
                                            <Label htmlFor="contact_id">
                                                Select contact
                                            </Label>
                                            <Select
                                                value={
                                                    form.data.contact_id
                                                        ? String(
                                                              form.data
                                                                  .contact_id,
                                                          )
                                                        : ''
                                                }
                                                onValueChange={(v) =>
                                                    form.setData(
                                                        'contact_id',
                                                        Number(v),
                                                    )
                                                }
                                            >
                                                <SelectTrigger id="contact_id">
                                                    <SelectValue placeholder="Choose an existing contact" />
                                                </SelectTrigger>
                                                <SelectContent>
                                                    {contacts.map((c) => (
                                                        <SelectItem
                                                            key={c.value}
                                                            value={String(
                                                                c.value,
                                                            )}
                                                        >
                                                            {c.label}
                                                        </SelectItem>
                                                    ))}
                                                </SelectContent>
                                            </Select>
                                            <InputError
                                                message={form.errors.contact_id}
                                            />
                                        </div>
                                    ) : (
                                        <div className="grid gap-4 sm:grid-cols-2">
                                            <div className="grid gap-2">
                                                <Label htmlFor="kind">
                                                    Kind
                                                </Label>
                                                <Select
                                                    value={
                                                        form.data.contact.kind
                                                    }
                                                    onValueChange={(v) =>
                                                        form.setData(
                                                            'contact',
                                                            {
                                                                ...form.data
                                                                    .contact,
                                                                kind: v,
                                                            },
                                                        )
                                                    }
                                                >
                                                    <SelectTrigger id="kind">
                                                        <SelectValue />
                                                    </SelectTrigger>
                                                    <SelectContent>
                                                        <SelectItem value="organization">
                                                            Organization
                                                        </SelectItem>
                                                        <SelectItem value="individual">
                                                            Individual
                                                        </SelectItem>
                                                    </SelectContent>
                                                </Select>
                                            </div>
                                            <div className="grid gap-2">
                                                <Label htmlFor="name">
                                                    Name
                                                </Label>
                                                <Input
                                                    id="name"
                                                    value={
                                                        form.data.contact.name
                                                    }
                                                    onChange={(e) =>
                                                        form.setData(
                                                            'contact',
                                                            {
                                                                ...form.data
                                                                    .contact,
                                                                name: e.target
                                                                    .value,
                                                            },
                                                        )
                                                    }
                                                    required
                                                />
                                                <InputError
                                                    message={
                                                        form.errors[
                                                            'contact.name' as keyof typeof form.errors
                                                        ]
                                                    }
                                                />
                                            </div>
                                            <div className="grid gap-2">
                                                <Label htmlFor="email">
                                                    Email (optional)
                                                </Label>
                                                <Input
                                                    id="email"
                                                    type="email"
                                                    value={
                                                        form.data.contact.email
                                                    }
                                                    onChange={(e) =>
                                                        form.setData(
                                                            'contact',
                                                            {
                                                                ...form.data
                                                                    .contact,
                                                                email: e.target
                                                                    .value,
                                                            },
                                                        )
                                                    }
                                                />
                                            </div>
                                            <div className="grid gap-2">
                                                <Label htmlFor="phone">
                                                    Phone (optional)
                                                </Label>
                                                <Input
                                                    id="phone"
                                                    value={
                                                        form.data.contact.phone
                                                    }
                                                    onChange={(e) =>
                                                        form.setData(
                                                            'contact',
                                                            {
                                                                ...form.data
                                                                    .contact,
                                                                phone: e.target
                                                                    .value,
                                                            },
                                                        )
                                                    }
                                                />
                                            </div>
                                        </div>
                                    )}
                                </CardContent>
                            </Card>
                        )}

                        <Card>
                            <CardHeader>
                                <CardTitle>Client details</CardTitle>
                            </CardHeader>
                            <CardContent className="grid gap-4 sm:grid-cols-2">
                                <div className="grid gap-2">
                                    <Label htmlFor="status">Status</Label>
                                    <Select
                                        value={form.data.status}
                                        onValueChange={(v) =>
                                            form.setData('status', v)
                                        }
                                    >
                                        <SelectTrigger id="status">
                                            <SelectValue />
                                        </SelectTrigger>
                                        <SelectContent>
                                            {statuses.map((s) => (
                                                <SelectItem
                                                    key={s.value}
                                                    value={String(s.value)}
                                                >
                                                    {s.label}
                                                </SelectItem>
                                            ))}
                                        </SelectContent>
                                    </Select>
                                </div>
                                <div className="grid gap-2">
                                    <Label htmlFor="partner">
                                        Relationship partner (optional)
                                    </Label>
                                    <Select
                                        value={
                                            form.data.relationship_partner_id
                                                ? String(
                                                      form.data
                                                          .relationship_partner_id,
                                                  )
                                                : NONE
                                        }
                                        onValueChange={(v) =>
                                            form.setData(
                                                'relationship_partner_id',
                                                v === NONE ? null : Number(v),
                                            )
                                        }
                                    >
                                        <SelectTrigger id="partner">
                                            <SelectValue placeholder="Unassigned" />
                                        </SelectTrigger>
                                        <SelectContent>
                                            <SelectItem value={NONE}>
                                                Unassigned
                                            </SelectItem>
                                            {partners.map((p) => (
                                                <SelectItem
                                                    key={p.value}
                                                    value={String(p.value)}
                                                >
                                                    {p.label}
                                                </SelectItem>
                                            ))}
                                        </SelectContent>
                                    </Select>
                                    <InputError
                                        message={
                                            form.errors.relationship_partner_id
                                        }
                                    />
                                </div>
                            </CardContent>
                        </Card>
                    </div>

                    <div className="lg:col-span-1">
                        <ConflictCheckWidget name={checkName} />
                    </div>
                </div>
            </form>
        </>
    );
}
