import InvoicePdfButton from '@/components/invoice-pdf-button';
import InvoiceForm, {
    BillingItemTypeOption,
    InvoiceFormValues,
    InvoicePaymentFormValues,
    createPayment,
    createPaymentItem,
} from '@/forms/account/InvoiceForm';
import AppLayout from '@/layouts/app-layout';
import { ClientInvoice } from '@/types';
import { Link, router, useForm } from '@inertiajs/react';
import { Badge, Button, Container, Group, Title } from '@mantine/core';
import { IconArrowLeft } from '@tabler/icons-react';
import React from 'react';

type InvoiceOptionSource = Pick<ClientInvoice, 'id' | 'invoice_no'> & {
    linked_invoice_id?: number | null;
};

type InvoicePaymentItemSource = {
    billing_item_types_id: number;
    start_date: string | null;
    end_date: string | null;
    payment_item_amount: string | number;
    tax_percentage: string | number;
    net_amount: string | number;
    withholding_tax: string | number;
    final_net_amount: string | number;
    spending: string | number;
    is_creditcard: boolean;
};

type InvoicePaymentSource = {
    payment_no: string | null;
    payment_total_amount: string | number;
    payment_nett_amount: string | number;
    items: InvoicePaymentItemSource[];
};

interface Props {
    invoice: ClientInvoice & {
        pending_sql_acc_code?: string | null;
        pending_client_name?: string | null;
        client?: {
            id: number;
            name: string;
            customer_id: string;
        };
        payments?: InvoicePaymentSource[];
        total_sem_amount?: number | string | null;
        total_net_amount?: number | string | null;
    };
    existingClient?: { id: number; name: string; customer_id: string } | null;
    unlinkedClients: { value: string; label: string }[];
    availableInvoices: InvoiceOptionSource[];
    billingItemTypes: BillingItemTypeOption[];
}

const valueString = (value: string | number | null | undefined) =>
    value === null || value === undefined ? '' : String(value);

const parseAmount = (value?: string | number | null) => {
    const parsed = Number.parseFloat(String(value ?? ''));

    return Number.isFinite(parsed) ? parsed : 0;
};

const finalNetAmount = (netAmount: number, withholdingTax: number) =>
    netAmount / (1 + withholdingTax / 100);

const paymentItemsFromInvoice = (
    invoice: Props['invoice'],
    billingItemTypes: BillingItemTypeOption[],
): InvoicePaymentFormValues[] => {
    if (invoice.payments?.length) {
        return invoice.payments.map((payment) => ({
            payment_no: payment.payment_no ?? '',
            payment_total_amount: valueString(payment.payment_total_amount),
            payment_nett_amount: valueString(payment.payment_nett_amount),
            items: payment.items.map((item) => ({
                billing_item_types_id: String(item.billing_item_types_id),
                start_date: item.start_date ?? '',
                end_date: item.end_date ?? '',
                payment_item_amount: valueString(item.payment_item_amount),
                tax_percentage: valueString(item.tax_percentage),
                net_amount: valueString(item.net_amount),
                withholding_tax: valueString(item.withholding_tax),
                final_net_amount: valueString(item.final_net_amount),
                spending: valueString(item.spending),
                is_creditcard: !!item.is_creditcard,
            })),
        }));
    }

    const mediaSearch = billingItemTypes.find(
        (itemType) => itemType.name === 'Google Ads Search (Media Fee)',
    );
    const managementSearch = billingItemTypes.find(
        (itemType) => itemType.name === 'Management Fee (Google Search Ads)',
    );
    const fallbackPayment = createPayment(billingItemTypes, {
        payment_no: invoice.payment_no ?? '',
        payment_total_amount: valueString(
            (Number(invoice.media_fee ?? 0) || 0) +
                (Number(invoice.management_fee ?? 0) || 0),
        ),
        payment_nett_amount: valueString(
            invoice.total_net_amount ?? invoice.nett_amount ?? 0,
        ),
    });

    return [
        {
            ...fallbackPayment,
            items: [
                createPaymentItem(
                    String(mediaSearch?.id ?? billingItemTypes[0]?.id ?? ''),
                    {
                        start_date: invoice.start_date ?? '',
                        end_date: invoice.end_date ?? '',
                        payment_item_amount: valueString(
                            invoice.media_fee ?? 0,
                        ),
                        tax_percentage: valueString(invoice.tax_percent ?? 0),
                        net_amount: valueString(
                            invoice.media_fee_amount ??
                                invoice.nett_amount ??
                                0,
                        ),
                        withholding_tax: '0',
                        final_net_amount: valueString(
                            invoice.nett_amount ??
                                invoice.media_fee_amount ??
                                0,
                        ),
                        spending: valueString(invoice.total_spending ?? 0),
                        is_creditcard: !!invoice.is_credit_card,
                    },
                ),
                createPaymentItem(
                    String(
                        managementSearch?.id ?? billingItemTypes[0]?.id ?? '',
                    ),
                    {
                        payment_item_amount: valueString(
                            invoice.management_fee ?? 0,
                        ),
                        tax_percentage: valueString(invoice.tax_percent ?? 0),
                        net_amount: valueString(
                            invoice.management_fee_amount ??
                                invoice.management_fee ??
                                0,
                        ),
                        withholding_tax: '0',
                        final_net_amount: valueString(
                            invoice.management_fee_amount ??
                                invoice.management_fee ??
                                0,
                        ),
                        spending: '0',
                    },
                ),
            ],
        },
    ];
};

export default function Page({
    invoice,
    existingClient,
    unlinkedClients,
    availableInvoices,
    billingItemTypes,
}: Props) {
    const resolvedClient = invoice.client ?? existingClient ?? null;
    const form = useForm<InvoiceFormValues>({
        invoice_no: invoice.invoice_no ?? '',
        linked_invoice_id: invoice.linked_invoice_id
            ? String(invoice.linked_invoice_id)
            : '',
        is_paid: !!invoice.is_paid,
        client_id: resolvedClient ? String(resolvedClient.id) : '',
        customer_id: resolvedClient?.customer_id ?? '',
        total_sem_amount: valueString(invoice.total_sem_amount ?? '0.00'),
        total_net_amount: valueString(
            invoice.total_net_amount ?? invoice.nett_amount ?? '0.00',
        ),
        payments: paymentItemsFromInvoice(invoice, billingItemTypes),
    });
    const isApproved = !!invoice.approved_at;

    const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
        event.preventDefault();

        form.transform((data) => ({
            ...data,
            linked_invoice_id: data.linked_invoice_id || null,
            is_paid: !!data.is_paid,
            total_sem_amount: parseFloat(data.total_sem_amount) || 0,
            total_net_amount: parseFloat(data.total_net_amount) || 0,
            payments: data.payments.map((payment) => ({
                ...payment,
                payment_no: payment.payment_no || null,
                payment_total_amount:
                    parseFloat(payment.payment_total_amount) || 0,
                payment_nett_amount:
                    parseFloat(payment.payment_nett_amount) || 0,
                items: payment.items.map((item) => ({
                    ...item,
                    start_date: item.start_date || null,
                    end_date: item.end_date || null,
                    billing_item_types_id: parseInt(
                        item.billing_item_types_id,
                        10,
                    ),
                    payment_item_amount: parseAmount(
                        item.payment_item_amount,
                    ),
                    tax_percentage: parseAmount(item.tax_percentage),
                    net_amount: parseAmount(item.net_amount),
                    withholding_tax: parseAmount(item.withholding_tax),
                    final_net_amount: finalNetAmount(
                        parseAmount(item.net_amount),
                        parseAmount(item.withholding_tax),
                    ),
                    spending: parseFloat(item.spending) || 0,
                    is_creditcard: !!item.is_creditcard,
                })),
            })),
        }));

        form.put(route('client-invoices.update', { invoice: invoice.id }));
    };

    const handleApprove = () => {
        router.patch(route('client-invoices.approve', { invoice: invoice.id }));
    };

    const invoiceOptions = availableInvoices.map((item) => ({
        value: String(item.id),
        label: item.invoice_no,
    }));
    const requiresClient = !invoice.client_id;

    return (
        <AppLayout>
            <Container size="lg" px="xs">
                <Group position="apart" mb="md">
                    <Group spacing="sm">
                        <Title order={2}>Edit invoice</Title>
                        <Badge
                            color={isApproved ? 'green' : 'yellow'}
                            variant="light"
                        >
                            {isApproved ? 'Approved' : 'Pending approval'}
                        </Badge>
                    </Group>
                    <Group spacing="sm">
                        {/* {!isApproved && (
                            <Button color="green" onClick={handleApprove}>
                                Approve invoice
                            </Button>
                        )} */}
                        <InvoicePdfButton
                            invoiceId={invoice.id}
                            invoiceNo={invoice.invoice_no}
                            display="button"
                            label="View invoice"
                        />
                        <Button
                            component={Link}
                            href={
                                resolvedClient?.customer_id
                                    ? route('google-ads.accounts.show', {
                                          id: resolvedClient.customer_id,
                                      })
                                    : route('dashboard')
                            }
                            leftIcon={<IconArrowLeft size={16} />}
                            variant="outline"
                        >
                            {resolvedClient ? 'Back to account' : 'Back'}
                        </Button>
                    </Group>
                </Group>

                <InvoiceForm
                    form={form}
                    onSubmit={handleSubmit}
                    invoiceOptions={invoiceOptions}
                    billingItemTypes={billingItemTypes}
                    showClientLink
                    requiresClient={requiresClient}
                    clientOptions={unlinkedClients}
                    pendingClientName={invoice.pending_client_name ?? null}
                />
            </Container>
        </AppLayout>
    );
}
