import { Head, Link, useForm } from '@inertiajs/react';
import type { FormEvent, ReactNode } from 'react';

type Option = { id: number; name: string };
type PartNumber = { type: string; number: string };
type Compatibility = {
    vehicle_make_id: number | string;
    vehicle_model_id: number | string;
    vehicle_generation_id: number | string | null;
    vehicle_engine_id: number | string | null;
    vehicle_transmission_id: number | string | null;
    year_from: number | string | null;
    year_to: number | string | null;
    engine_code: string | null;
    transmission_type: string | null;
    drive_type: string | null;
    chassis_code: string | null;
    notes: string | null;
};
type ProductImage = {
    path: string;
    type: string;
    alt_text: string;
    sort_order: number;
    is_main: boolean;
};
type SpecificationValue = {
    specification_field_id: number | string;
    value: string;
};
type SpecificationGroup = {
    id: number;
    name: string;
    fields: {
        id: number;
        name: string;
        type: string;
        unit: string | null;
        is_required: boolean;
    }[];
};
type Product = {
    id: number;
    brand_id: number | null;
    category_id: number | null;
    name: string;
    slug: string;
    sku: string;
    barcode: string | null;
    system_type: string | null;
    description: string | null;
    condition: string;
    status: string;
    price: string;
    discount_price: string | null;
    stock_quantity: number;
    reserved_quantity: number;
    warehouse_location: string | null;
    shelf_location: string | null;
    minimum_stock: number;
    seo_title: string | null;
    meta_description: string | null;
    canonical_url: string | null;
    opengraph_image: string | null;
    part_numbers: PartNumber[];
    images: ProductImage[];
    tags: { name: string }[];
    compatibilities: Compatibility[];
    specification_values: SpecificationValue[];
};
type VehicleMake = {
    id: number;
    name: string;
    models: Option[];
};

const emptyProduct = {
    brand_id: '',
    category_id: '',
    name: '',
    slug: '',
    sku: '',
    barcode: '',
    system_type: '',
    description: '',
    condition: 'new',
    status: 'draft',
    price: '0.00',
    discount_price: '',
    stock_quantity: 0,
    reserved_quantity: 0,
    warehouse_location: '',
    shelf_location: '',
    minimum_stock: 0,
    seo_title: '',
    meta_description: '',
    canonical_url: '',
    opengraph_image: '',
    part_numbers: [{ type: 'oem', number: '' }],
    compatibilities: [],
    images: [],
    tags: '',
    specification_values: [],
};

export default function ProductForm({
    product,
    brands,
    categories,
    specificationGroups,
    vehicleMakes,
}: {
    product: Product | null;
    brands: Option[];
    categories: Option[];
    specificationGroups: SpecificationGroup[];
    vehicleMakes: VehicleMake[];
}) {
    const { data, setData, transform, post, put, processing, errors } = useForm({
        ...emptyProduct,
        ...(product
            ? {
                  ...product,
                  brand_id: product.brand_id ?? '',
                  category_id: product.category_id ?? '',
                  barcode: product.barcode ?? '',
                  system_type: product.system_type ?? '',
                  description: product.description ?? '',
                  discount_price: product.discount_price ?? '',
                  warehouse_location: product.warehouse_location ?? '',
                  shelf_location: product.shelf_location ?? '',
                  seo_title: product.seo_title ?? '',
                  meta_description: product.meta_description ?? '',
                  canonical_url: product.canonical_url ?? '',
                  opengraph_image: product.opengraph_image ?? '',
                  tags: product.tags.map((tag) => tag.name).join(', '),
              }
            : {}),
    });

    function submit(event: FormEvent) {
        event.preventDefault();

        const payload = {
            ...data,
            brand_id: data.brand_id || null,
            category_id: data.category_id || null,
            discount_price: data.discount_price || null,
            tags: String(data.tags)
                .split(',')
                .map((tag) => tag.trim())
                .filter(Boolean),
            part_numbers: data.part_numbers.filter((item) => item.number),
            compatibilities: data.compatibilities.filter(
                (item) => item.vehicle_make_id && item.vehicle_model_id,
            ),
            specification_values: data.specification_values.filter(
                (item) => item.specification_field_id && item.value,
            ),
        };

        transform(() => payload);

        if (product) {
            put(`/admin/products/${product.id}`);

            return;
        }

        post('/admin/products');
    }

    function updatePartNumber(index: number, value: Partial<PartNumber>) {
        const partNumbers = [...data.part_numbers];
        partNumbers[index] = { ...partNumbers[index], ...value };
        setData('part_numbers', partNumbers);
    }

    function addCompatibility() {
        setData('compatibilities', [
            ...data.compatibilities,
            {
                vehicle_make_id: '',
                vehicle_model_id: '',
                vehicle_generation_id: null,
                vehicle_engine_id: null,
                vehicle_transmission_id: null,
                year_from: '',
                year_to: '',
                engine_code: '',
                transmission_type: '',
                drive_type: '',
                chassis_code: '',
                notes: '',
            },
        ]);
    }

    function updateCompatibility(index: number, value: Partial<Compatibility>) {
        const compatibilities = [...data.compatibilities];
        compatibilities[index] = { ...compatibilities[index], ...value };
        setData('compatibilities', compatibilities);
    }

    function removeCompatibility(index: number) {
        setData(
            'compatibilities',
            data.compatibilities.filter((_, itemIndex) => itemIndex !== index),
        );
    }

    function specificationValue(fieldId: number) {
        return (
            data.specification_values.find(
                (item) => String(item.specification_field_id) === String(fieldId),
            )?.value ?? ''
        );
    }

    function updateSpecificationValue(fieldId: number, value: string) {
        const values = data.specification_values.filter(
            (item) => String(item.specification_field_id) !== String(fieldId),
        );

        if (value) {
            values.push({ specification_field_id: fieldId, value });
        }

        setData('specification_values', values);
    }

    function modelsForMake(makeId: number | string) {
        return (
            vehicleMakes.find((make) => String(make.id) === String(makeId))
                ?.models ?? []
        );
    }

    return (
        <>
            <Head title={product ? 'Edit Product' : 'Create Product'} />
            <main className="min-h-screen bg-slate-50 px-4 py-6 text-slate-900 sm:px-6 lg:px-8">
                <form onSubmit={submit} className="mx-auto max-w-5xl">
                    <div className="mb-6 flex flex-col gap-3 border-b border-slate-200 pb-5 sm:flex-row sm:items-end sm:justify-between">
                        <div>
                            <p className="text-sm font-medium text-cyan-700">
                                Catalog admin
                            </p>
                            <h1 className="text-2xl font-semibold">
                                {product ? 'Edit product' : 'Create product'}
                            </h1>
                        </div>
                        <div className="flex gap-2">
                            <Link
                                href="/admin/products"
                                className="rounded-md border border-slate-300 bg-white px-4 py-2 text-sm font-semibold text-slate-800"
                            >
                                Cancel
                            </Link>
                            <button
                                disabled={processing}
                                className="rounded-md bg-cyan-700 px-4 py-2 text-sm font-semibold text-white hover:bg-cyan-800 disabled:opacity-60"
                            >
                                Save
                            </button>
                        </div>
                    </div>

                    <section className="grid gap-5 rounded-lg border border-slate-200 bg-white p-4 md:grid-cols-2">
                        <Field label="Name" error={errors.name}>
                            <input
                                value={data.name}
                                onChange={(event) =>
                                    setData('name', event.target.value)
                                }
                                className="input"
                            />
                        </Field>
                        <Field label="Slug" error={errors.slug}>
                            <input
                                value={data.slug}
                                onChange={(event) =>
                                    setData('slug', event.target.value)
                                }
                                className="input"
                            />
                        </Field>
                        <Field label="SKU" error={errors.sku}>
                            <input
                                value={data.sku}
                                onChange={(event) =>
                                    setData('sku', event.target.value)
                                }
                                className="input"
                            />
                        </Field>
                        <Field label="Barcode / EAN" error={errors.barcode}>
                            <input
                                value={data.barcode}
                                onChange={(event) =>
                                    setData('barcode', event.target.value)
                                }
                                className="input"
                            />
                        </Field>
                        <Field label="Brand" error={errors.brand_id}>
                            <select
                                value={data.brand_id}
                                onChange={(event) =>
                                    setData('brand_id', event.target.value)
                                }
                                className="input"
                            >
                                <option value="">No brand</option>
                                {brands.map((brand) => (
                                    <option key={brand.id} value={brand.id}>
                                        {brand.name}
                                    </option>
                                ))}
                            </select>
                        </Field>
                        <Field label="Category" error={errors.category_id}>
                            <select
                                value={data.category_id}
                                onChange={(event) =>
                                    setData('category_id', event.target.value)
                                }
                                className="input"
                            >
                                <option value="">No category</option>
                                {categories.map((category) => (
                                    <option
                                        key={category.id}
                                        value={category.id}
                                    >
                                        {category.name}
                                    </option>
                                ))}
                            </select>
                        </Field>
                        <Field label="System type" error={errors.system_type}>
                            <input
                                value={data.system_type}
                                onChange={(event) =>
                                    setData('system_type', event.target.value)
                                }
                                className="input"
                            />
                        </Field>
                        <Field label="Condition" error={errors.condition}>
                            <select
                                value={data.condition}
                                onChange={(event) =>
                                    setData('condition', event.target.value)
                                }
                                className="input"
                            >
                                <option value="new">New</option>
                                <option value="used">Used</option>
                                <option value="refurbished">Refurbished</option>
                            </select>
                        </Field>
                        <Field label="Status" error={errors.status}>
                            <select
                                value={data.status}
                                onChange={(event) =>
                                    setData('status', event.target.value)
                                }
                                className="input"
                            >
                                <option value="draft">Draft</option>
                                <option value="active">Active</option>
                                <option value="out_of_stock">
                                    Out of stock
                                </option>
                                <option value="archived">Archived</option>
                            </select>
                        </Field>
                        <Field label="Price" error={errors.price}>
                            <input
                                value={data.price}
                                onChange={(event) =>
                                    setData('price', event.target.value)
                                }
                                className="input"
                                type="number"
                                min="0"
                                step="0.01"
                            />
                        </Field>
                        <Field
                            label="Discount price"
                            error={errors.discount_price}
                        >
                            <input
                                value={data.discount_price}
                                onChange={(event) =>
                                    setData(
                                        'discount_price',
                                        event.target.value,
                                    )
                                }
                                className="input"
                                type="number"
                                min="0"
                                step="0.01"
                            />
                        </Field>
                        <Field label="Stock" error={errors.stock_quantity}>
                            <input
                                value={data.stock_quantity}
                                onChange={(event) =>
                                    setData(
                                        'stock_quantity',
                                        Number(event.target.value),
                                    )
                                }
                                className="input"
                                type="number"
                                min="0"
                            />
                        </Field>
                        <Field
                            label="Reserved"
                            error={errors.reserved_quantity}
                        >
                            <input
                                value={data.reserved_quantity}
                                onChange={(event) =>
                                    setData(
                                        'reserved_quantity',
                                        Number(event.target.value),
                                    )
                                }
                                className="input"
                                type="number"
                                min="0"
                            />
                        </Field>
                        <Field
                            label="Warehouse location"
                            error={errors.warehouse_location}
                        >
                            <input
                                value={data.warehouse_location}
                                onChange={(event) =>
                                    setData(
                                        'warehouse_location',
                                        event.target.value,
                                    )
                                }
                                className="input"
                            />
                        </Field>
                        <Field
                            label="Shelf location"
                            error={errors.shelf_location}
                        >
                            <input
                                value={data.shelf_location}
                                onChange={(event) =>
                                    setData('shelf_location', event.target.value)
                                }
                                className="input"
                            />
                        </Field>
                        <Field label="Minimum stock" error={errors.minimum_stock}>
                            <input
                                value={data.minimum_stock}
                                onChange={(event) =>
                                    setData(
                                        'minimum_stock',
                                        Number(event.target.value),
                                    )
                                }
                                className="input"
                                type="number"
                                min="0"
                            />
                        </Field>
                        <Field label="Tags" error={errors.tags}>
                            <input
                                value={data.tags}
                                onChange={(event) =>
                                    setData('tags', event.target.value)
                                }
                                className="input"
                                placeholder="BMW, E46, VANOS"
                            />
                        </Field>
                        <Field label="Description" error={errors.description}>
                            <textarea
                                value={data.description}
                                onChange={(event) =>
                                    setData('description', event.target.value)
                                }
                                className="input min-h-28"
                            />
                        </Field>
                    </section>

                    <section className="mt-5 rounded-lg border border-slate-200 bg-white p-4">
                        <h2 className="text-lg font-semibold">
                            Technical specifications
                        </h2>
                        <div className="mt-4 grid gap-5">
                            {specificationGroups.map((group) => (
                                <div key={group.id}>
                                    <h3 className="text-sm font-semibold text-slate-700">
                                        {group.name}
                                    </h3>
                                    <div className="mt-3 grid gap-3 md:grid-cols-2">
                                        {group.fields.map((field) => (
                                            <Field
                                                key={field.id}
                                                label={`${field.name}${field.unit ? ` (${field.unit})` : ''}`}
                                            >
                                                <input
                                                    value={specificationValue(
                                                        field.id,
                                                    )}
                                                    onChange={(event) =>
                                                        updateSpecificationValue(
                                                            field.id,
                                                            event.target.value,
                                                        )
                                                    }
                                                    className="input"
                                                    required={field.is_required}
                                                    type={
                                                        field.type === 'number'
                                                            ? 'number'
                                                            : 'text'
                                                    }
                                                />
                                            </Field>
                                        ))}
                                    </div>
                                </div>
                            ))}
                            {specificationGroups.length === 0 ? (
                                <p className="text-sm text-slate-500">
                                    No specification fields configured yet.
                                </p>
                            ) : null}
                        </div>
                    </section>

                    <section className="mt-5 rounded-lg border border-slate-200 bg-white p-4">
                        <div className="mb-4 flex items-center justify-between">
                            <h2 className="text-lg font-semibold">
                                Part numbers
                            </h2>
                            <button
                                type="button"
                                onClick={() =>
                                    setData('part_numbers', [
                                        ...data.part_numbers,
                                        { type: 'alternative', number: '' },
                                    ])
                                }
                                className="rounded-md border border-slate-300 px-3 py-2 text-sm font-semibold"
                            >
                                Add number
                            </button>
                        </div>
                        <div className="grid gap-3">
                            {data.part_numbers.map((partNumber, index) => (
                                <div
                                    key={index}
                                    className="grid gap-3 sm:grid-cols-[180px_1fr]"
                                >
                                    <select
                                        value={partNumber.type}
                                        onChange={(event) =>
                                            updatePartNumber(index, {
                                                type: event.target.value,
                                            })
                                        }
                                        className="input"
                                    >
                                        <option value="oem">OEM</option>
                                        <option value="original">
                                            Original
                                        </option>
                                        <option value="alternative">
                                            Alternative
                                        </option>
                                        <option value="replacement">
                                            Replacement
                                        </option>
                                        <option value="supplier">Supplier</option>
                                        <option value="internal_sku">
                                            Internal SKU
                                        </option>
                                        <option value="aftermarket">
                                            Aftermarket
                                        </option>
                                    </select>
                                    <input
                                        value={partNumber.number}
                                        onChange={(event) =>
                                            updatePartNumber(index, {
                                                number: event.target.value,
                                            })
                                        }
                                        className="input"
                                    />
                                </div>
                            ))}
                        </div>
                    </section>

                    <section className="mt-5 rounded-lg border border-slate-200 bg-white p-4">
                        <div className="mb-4 flex items-center justify-between">
                            <h2 className="text-lg font-semibold">
                                Vehicle compatibility
                            </h2>
                            <button
                                type="button"
                                onClick={addCompatibility}
                                className="rounded-md border border-slate-300 px-3 py-2 text-sm font-semibold"
                            >
                                Add vehicle
                            </button>
                        </div>
                        <div className="grid gap-4">
                            {data.compatibilities.map(
                                (compatibility, index) => (
                                    <div
                                        key={index}
                                        className="rounded-md border border-slate-200 p-3"
                                    >
                                        <div className="grid gap-3 md:grid-cols-2">
                                            <Field label="Make">
                                                <select
                                                    value={
                                                        compatibility.vehicle_make_id ??
                                                        ''
                                                    }
                                                    onChange={(event) =>
                                                        updateCompatibility(
                                                            index,
                                                            {
                                                                vehicle_make_id:
                                                                    event.target
                                                                        .value,
                                                                vehicle_model_id:
                                                                    '',
                                                            },
                                                        )
                                                    }
                                                    className="input"
                                                >
                                                    <option value="">
                                                        Select make
                                                    </option>
                                                    {vehicleMakes.map((make) => (
                                                        <option
                                                            key={make.id}
                                                            value={make.id}
                                                        >
                                                            {make.name}
                                                        </option>
                                                    ))}
                                                </select>
                                            </Field>
                                            <Field label="Model">
                                                <select
                                                    value={
                                                        compatibility.vehicle_model_id ??
                                                        ''
                                                    }
                                                    onChange={(event) =>
                                                        updateCompatibility(
                                                            index,
                                                            {
                                                                vehicle_model_id:
                                                                    event.target
                                                                        .value,
                                                            },
                                                        )
                                                    }
                                                    className="input"
                                                >
                                                    <option value="">
                                                        Select model
                                                    </option>
                                                    {modelsForMake(
                                                        compatibility.vehicle_make_id,
                                                    ).map((model) => (
                                                        <option
                                                            key={model.id}
                                                            value={model.id}
                                                        >
                                                            {model.name}
                                                        </option>
                                                    ))}
                                                </select>
                                            </Field>
                                            <Field label="Year from">
                                                <input
                                                    value={
                                                        compatibility.year_from ??
                                                        ''
                                                    }
                                                    onChange={(event) =>
                                                        updateCompatibility(
                                                            index,
                                                            {
                                                                year_from:
                                                                    event.target
                                                                        .value,
                                                            },
                                                        )
                                                    }
                                                    className="input"
                                                    type="number"
                                                    min="1900"
                                                    max="2100"
                                                />
                                            </Field>
                                            <Field label="Year to">
                                                <input
                                                    value={
                                                        compatibility.year_to ??
                                                        ''
                                                    }
                                                    onChange={(event) =>
                                                        updateCompatibility(
                                                            index,
                                                            {
                                                                year_to:
                                                                    event.target
                                                                        .value,
                                                            },
                                                        )
                                                    }
                                                    className="input"
                                                    type="number"
                                                    min="1900"
                                                    max="2100"
                                                />
                                            </Field>
                                            <Field label="Engine code">
                                                <input
                                                    value={
                                                        compatibility.engine_code ??
                                                        ''
                                                    }
                                                    onChange={(event) =>
                                                        updateCompatibility(
                                                            index,
                                                            {
                                                                engine_code:
                                                                    event.target
                                                                        .value,
                                                            },
                                                        )
                                                    }
                                                    className="input"
                                                />
                                            </Field>
                                            <Field label="Transmission">
                                                <select
                                                    value={
                                                        compatibility.transmission_type ??
                                                        ''
                                                    }
                                                    onChange={(event) =>
                                                        updateCompatibility(
                                                            index,
                                                            {
                                                                transmission_type:
                                                                    event.target
                                                                        .value,
                                                            },
                                                        )
                                                    }
                                                    className="input"
                                                >
                                                    <option value="">
                                                        Any transmission
                                                    </option>
                                                    <option value="manual">
                                                        Manual
                                                    </option>
                                                    <option value="automatic">
                                                        Automatic
                                                    </option>
                                                </select>
                                            </Field>
                                            <Field label="Drive type">
                                                <input
                                                    value={
                                                        compatibility.drive_type ??
                                                        ''
                                                    }
                                                    onChange={(event) =>
                                                        updateCompatibility(
                                                            index,
                                                            {
                                                                drive_type:
                                                                    event.target
                                                                        .value,
                                                            },
                                                        )
                                                    }
                                                    className="input"
                                                />
                                            </Field>
                                            <Field label="Chassis code">
                                                <input
                                                    value={
                                                        compatibility.chassis_code ??
                                                        ''
                                                    }
                                                    onChange={(event) =>
                                                        updateCompatibility(
                                                            index,
                                                            {
                                                                chassis_code:
                                                                    event.target
                                                                        .value,
                                                            },
                                                        )
                                                    }
                                                    className="input"
                                                />
                                            </Field>
                                        </div>
                                        <button
                                            type="button"
                                            onClick={() =>
                                                removeCompatibility(index)
                                            }
                                            className="mt-3 text-sm font-semibold text-red-700"
                                        >
                                            Remove vehicle
                                        </button>
                                    </div>
                                ),
                            )}
                            {data.compatibilities.length === 0 ? (
                                <p className="text-sm text-slate-500">
                                    No compatibility rows added.
                                </p>
                            ) : null}
                        </div>
                    </section>
                </form>
            </main>
        </>
    );
}

function Field({
    label,
    error,
    children,
}: {
    label: string;
    error?: string;
    children: ReactNode;
}) {
    return (
        <label className="grid gap-1 text-sm font-medium text-slate-700">
            <span>{label}</span>
            {children}
            {error ? <span className="text-xs text-red-600">{error}</span> : null}
        </label>
    );
}
