import { useState } from 'react';
import { Head, Link, router } from '@inertiajs/react';
import { Building2, FileSpreadsheet, Plus, UserRound, Users } from 'lucide-react';
import { NativeSelect } from '@/components/crm/native-select';
import { EmptyState, PageHeader } from '@/components/crm/page-header';
import { StatusPill } from '@/components/crm/status-badge';
import {
    ActiveFilters,
    DataPagination,
    FilterBar,
    FilterField,
    SearchInput,
    TableCard,
} from '@/components/crm/toolbar';
import { Button } from '@/components/ui/button';
import {
    Table,
    TableBody,
    TableCell,
    TableHead,
    TableHeader,
    TableRow,
} from '@/components/ui/table';
import { formatDate, formatNumber, formatRelative } from '@/lib/format';
import { create as customerCreate, index as customersIndex, show as customerShow } from '@/routes/customers';
import type { CustomerSummary, Option, Paginated } from '@/types';

type Filters = {
    search: string | null;
    type: string | null;
    state: string | null;
    status: string | null;
};

type PageProps = {
    customers: Paginated<CustomerSummary>;
    filters: Filters;
    filterOptions: {
        types: Option[];
        states: Option[];
        statuses: Option[];
    };
    can: {
        create: boolean;
        update: boolean;
        delete: boolean;
        viewFinancials: boolean;
        importInformation: boolean;
    };
    pendingChangeRequests: number;
};

export default function CustomersIndex({
    customers,
    filters,
    filterOptions,
    can,
    pendingChangeRequests,
}: PageProps) {
    const [search, setSearch] = useState(filters.search ?? '');

    /**
     * Filtering happens on the server, so every change is a fresh GET with the
     * current filters merged in. Empty values are dropped so the URL stays
     * clean and shareable.
     */
    const navigate = (next: Partial<Filters>) => {
        const merged: Filters = { ...filters, ...next };
        const params: Record<string, string> = {};

        Object.entries(merged).forEach(([key, value]) => {
            if (value !== null && value !== undefined && value !== '') {
                params[key] = String(value);
            }
        });

        router.get(customersIndex().url, params, {
            preserveState: true,
            replace: true,
        });
    };

    const resetAll = () => {
        setSearch('');
        router.get(customersIndex().url);
    };

    const hasFilters =
        Boolean(filters.search) ||
        Boolean(filters.type) ||
        Boolean(filters.state) ||
        (filters.status ?? 'active') !== 'active';

    /**
     * The applied filters as removable chips, so it is always obvious why the
     * list is showing what it is showing.
     */
    type AppliedFilter = {
        key: string;
        label: string;
        value: string;
        onRemove: () => void;
    };

    const filterChips: Array<AppliedFilter | null> = [
        filters.search
            ? {
                  key: 'search',
                  label: 'Search',
                  value: filters.search,
                  onRemove: () => {
                      setSearch('');
                      navigate({ search: null });
                  },
              }
            : null,
        filters.type
            ? {
                  key: 'type',
                  label: 'Type',
                  value:
                      filterOptions.types.find(
                          (option) => option.value === filters.type,
                      )?.label ?? filters.type,
                  onRemove: () => navigate({ type: null }),
              }
            : null,
        filters.state
            ? {
                  key: 'state',
                  label: 'State',
                  value:
                      filterOptions.states.find(
                          (option) => option.value === filters.state,
                      )?.label ?? filters.state,
                  onRemove: () => navigate({ state: null }),
              }
            : null,
        filters.status && filters.status !== 'active'
            ? {
                  key: 'status',
                  label: 'Status',
                  value:
                      filterOptions.statuses.find(
                          (option) => option.value === filters.status,
                      )?.label ?? filters.status,
                  onRemove: () => navigate({ status: 'active' }),
              }
            : null,
    ];

    const appliedFilters = filterChips.filter(
        (filter): filter is AppliedFilter => filter !== null,
    );

    return (
        <>
            <Head title="Customers" />

            <PageHeader
                eyebrow={
                    <>
                        <Building2 className="size-3.5 text-solar" />
                        <span>
                            {formatNumber(customers.total)} customers
                            {hasFilters ? ' matching these filters' : ''}
                        </span>
                    </>
                }
                title="Customers"
                description="Every household, business and builder account, with the sites and jobs against them."
                actions={
                    <div className="flex flex-wrap items-center gap-2">
                        {can.importInformation ? (
                            <Button size="sm" variant="outline" asChild>
                                <Link href="/customers/information-import">
                                    <FileSpreadsheet />
                                    Client information import
                                </Link>
                            </Button>
                        ) : null}
                        {can.update ? (
                            <Button size="sm" variant="outline" asChild>
                                <Link href="/customers/profile-changes">
                                    <UserRound />
                                    Profile updates
                                    {pendingChangeRequests > 0 ? (
                                        <span className="ml-1 inline-flex min-w-5 items-center justify-center rounded-full bg-amber-500/15 px-1.5 text-[11px] font-semibold text-amber-800 dark:text-amber-300">
                                            {pendingChangeRequests}
                                        </span>
                                    ) : null}
                                </Link>
                            </Button>
                        ) : null}
                        {can.create ? (
                            <Button size="sm" asChild>
                                <Link href={customerCreate()}>
                                    <Plus />
                                    New customer
                                </Link>
                            </Button>
                        ) : null}
                    </div>
                }
            />

            <form
                onSubmit={(event) => {
                    event.preventDefault();
                    navigate({ search: search || null });
                }}
            >
                <FilterBar
                    actions={
                        <>
                            <Button type="submit" size="sm">
                                Apply
                            </Button>
                            {hasFilters ? (
                                <Button
                                    type="button"
                                    variant="ghost"
                                    size="sm"
                                    onClick={resetAll}
                                >
                                    Reset
                                </Button>
                            ) : null}
                        </>
                    }
                >
                    <SearchInput
                        value={search}
                        onChange={setSearch}
                        placeholder="Search name, number, email, phone, ABN, suburb or postcode"
                    />

                    <FilterField label="Type" className="w-40">
                        <NativeSelect
                            className="h-9"
                            value={filters.type ?? ''}
                            onChange={(event) =>
                                navigate({ type: event.target.value || null })
                            }
                            aria-label="Filter by customer type"
                        >
                            <option value="">All types</option>
                            {filterOptions.types.map((option) => (
                                <option key={option.value} value={option.value}>
                                    {option.label}
                                </option>
                            ))}
                        </NativeSelect>
                    </FilterField>

                    <FilterField label="State" className="w-40">
                        <NativeSelect
                            className="h-9"
                            value={filters.state ?? ''}
                            onChange={(event) =>
                                navigate({ state: event.target.value || null })
                            }
                            aria-label="Filter by state"
                        >
                            <option value="">All states</option>
                            {filterOptions.states.map((option) => (
                                <option key={option.value} value={option.value}>
                                    {option.label}
                                </option>
                            ))}
                        </NativeSelect>
                    </FilterField>

                    <FilterField label="Status" className="w-36">
                        <NativeSelect
                            className="h-9"
                            value={filters.status ?? 'active'}
                            onChange={(event) =>
                                navigate({ status: event.target.value })
                            }
                            aria-label="Filter by status"
                        >
                            {filterOptions.statuses.map((option) => (
                                <option key={option.value} value={option.value}>
                                    {option.label}
                                </option>
                            ))}
                        </NativeSelect>
                    </FilterField>
                </FilterBar>
            </form>

            <ActiveFilters filters={[...appliedFilters]} onClear={resetAll} />

            {customers.data.length === 0 ? (
                <EmptyState
                    icon={Users}
                    title="No customers found"
                    description={
                        hasFilters
                            ? 'Try clearing the filters or searching for something else.'
                            : 'Add your first customer to start recording sites and jobs.'
                    }
                    action={
                        can.create ? (
                            <Button asChild size="sm">
                                <Link href={customerCreate()}>
                                    New customer
                                </Link>
                            </Button>
                        ) : null
                    }
                />
            ) : (
                <TableCard>
                    <Table>
                        <TableHeader>
                            <TableRow>
                                <TableHead className="pl-5">Customer</TableHead>
                                <TableHead>Type</TableHead>
                                <TableHead>Contact</TableHead>
                                <TableHead>Primary site</TableHead>
                                <TableHead className="text-right">
                                    Jobs
                                </TableHead>
                                <TableHead>Owner</TableHead>
                                <TableHead className="pr-5">Added</TableHead>
                            </TableRow>
                        </TableHeader>
                        <TableBody>
                            {customers.data.map((customer) => (
                                <TableRow key={customer.id}>
                                    <TableCell className="min-w-56 pl-5">
                                        <Link
                                            href={customerShow(customer.id)}
                                            className="text-sm font-medium hover:underline"
                                        >
                                            {customer.name}
                                        </Link>
                                        <div className="text-muted-foreground mt-0.5 font-mono text-[11px]">
                                            {customer.customer_number}
                                            {customer.abn
                                                ? ` · ABN ${customer.abn}`
                                                : ''}
                                        </div>
                                        {customer.builder ? (
                                            <div className="text-muted-foreground mt-0.5 text-[11px]">
                                                Under {customer.builder.name}
                                            </div>
                                        ) : null}
                                    </TableCell>
                                    <TableCell>
                                        <StatusPill
                                            tone={
                                                customer.type.is_organisation
                                                    ? 'violet'
                                                    : 'blue'
                                            }
                                        >
                                            {customer.type.label}
                                        </StatusPill>
                                    </TableCell>
                                    <TableCell className="min-w-48">
                                        <div className="text-sm">
                                            {customer.email ?? '—'}
                                        </div>
                                        <div className="text-muted-foreground mt-0.5 text-xs">
                                            {customer.phone ?? '—'}
                                            {customer.last_contacted_at
                                                ? ` · Last contacted ${formatRelative(customer.last_contacted_at)}`
                                                : ''}
                                        </div>
                                    </TableCell>
                                    <TableCell className="min-w-56">
                                        {customer.primary_site ? (
                                            <>
                                                <div className="text-sm">
                                                    {
                                                        customer.primary_site
                                                            .address
                                                    }
                                                </div>
                                                <div className="text-muted-foreground mt-0.5 text-xs">
                                                    {customer.primary_site
                                                        .distribution_network ??
                                                        'Network not set'}
                                                </div>
                                            </>
                                        ) : (
                                            <span className="text-muted-foreground text-xs">
                                                No site recorded
                                            </span>
                                        )}
                                    </TableCell>
                                    <TableCell className="text-right">
                                        <div className="crm-num text-sm font-medium">
                                            {formatNumber(
                                                customer.active_jobs_count,
                                            )}
                                            <span className="text-muted-foreground ml-1 text-xs font-normal">
                                                active
                                            </span>
                                        </div>
                                        <div className="crm-num text-muted-foreground mt-0.5 text-xs">
                                            {formatNumber(customer.jobs_count)}{' '}
                                            total
                                        </div>
                                    </TableCell>
                                    <TableCell className="text-sm">
                                        {customer.owner?.name ?? '—'}
                                    </TableCell>
                                    <TableCell className="text-muted-foreground pr-5 text-xs whitespace-nowrap">
                                        {formatDate(customer.created_at)}
                                    </TableCell>
                                </TableRow>
                            ))}
                        </TableBody>
                    </Table>

                    <DataPagination page={customers} noun="customers" />
                </TableCard>
            )}
        </>
    );
}

CustomersIndex.layout = {
    breadcrumbs: [
        {
            title: 'Customers',
            href: customersIndex(),
        },
    ],
};
