import { FC, useCallback, useEffect, useRef, useState } from 'react'
import { useGetAllCompanies } from '../company/hooks/useCompanyData'
import { useFormik } from 'formik'
import * as Yup from 'yup'
import { useDropzone } from 'react-dropzone'
import { CreateBillType } from './types/Types'
import { useCreateBill, useCreateBillWithExcel } from './hooks/useBillData'
import Button from '../../components/Button'
import Input from '../../components/Input'
import { DocumentUpload, TickCircle } from 'iconsax-react'
import { toast } from 'react-toastify'
import { ErrorType } from '../../helpers/types'
import { Pages } from '../../config/Pages'
import { useNavigate } from 'react-router-dom'
import { CompanyItemType } from '../company/types/CompanyTypes'
import PageLoading from '../../components/PageLoading'

const CreateBill: FC = () => {
    const navigate = useNavigate()
    const getCompanies = useGetAllCompanies()
    const createBill = useCreateBill()
    const createBillWithExcel = useCreateBillWithExcel()
    const [excelFile, setExcelFile] = useState<File | null>(null)

    const onDropExcel = useCallback((acceptedFiles: File[]) => {
        setExcelFile(acceptedFiles[0] ?? null)
    }, [])
    const { getRootProps, getInputProps } = useDropzone({
        onDrop: onDropExcel,
        accept: {
            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': ['.xlsx'],
            'application/vnd.ms-excel': ['.xls'],
        },
        maxFiles: 1,
        multiple: false,
    })

    const companies: CompanyItemType[] = getCompanies.data?.data?.companies ?? []

    const formik = useFormik<CreateBillType>({
        initialValues: {
            waterRate: 0,
            dueDays: 0,
            values: [],
        },
        enableReinitialize: true,
        validationSchema: Yup.object({
            waterRate: Yup.number().min(0, 'نرخ آب باید عدد مثبت باشد').required('نرخ آب الزامی است'),
            dueDays: Yup.number().min(0, 'تعداد روز مهلت باید عدد مثبت باشد').required('تعداد روز مهلت الزامی است'),
            values: Yup.array()
                .of(
                    Yup.object({
                        companyId: Yup.string().required(),
                        waterUsage: Yup.number().min(0, 'مصرف آب باید عدد مثبت باشد').required('مصرف آب الزامی است'),
                    })
                )
                .min(1, 'حداقل یک شرکت باید مصرف داشته باشد')
                .required('اطلاعات مصرف شرکت‌ها الزامی است'),
        }),
        onSubmit: async (values) => {
            const filteredValues = values.values.filter((v) => v.companyId && (v.waterUsage ?? 0) >= 0)
            if (filteredValues.length === 0) {
                toast.error('حداقل یک شرکت با مصرف معتبر وارد کنید')
                return
            }

            values.dueDays = Number(values.dueDays)
            values.waterRate = Number(values.waterRate)

            await createBill.mutateAsync(
                { ...values, values: filteredValues },
                {
                    onSuccess: () => {
                        toast.success('قبض آب با موفقیت ثبت شد')
                        navigate(Pages.bill.list)
                    },
                    onError: (error: ErrorType) => {
                        toast.error(error.response?.data?.error?.message?.[0] ?? 'خطا در ثبت قبض')
                    },
                }
            )
        },
    })

    const initializedRef = useRef(false)
    useEffect(() => {
        if (companies.length > 0 && !initializedRef.current) {
            initializedRef.current = true
            formik.setFieldValue(
                'values',
                companies.map((c) => ({ companyId: c.id, waterUsage: 0 }))
            )
        }
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [companies])

    if (getCompanies.isLoading) {
        return <PageLoading />
    }

    if (companies.length === 0 && !getCompanies.isLoading) {
        return (
            <div className="mt-4 p-6 bg-white rounded-3xl text-center text-gray-600">
                شرکتی ثبت نشده است. ابتدا شرکت اضافه کنید.
            </div>
        )
    }

    const setWaterUsage = (companyId: string, waterUsage: number) => {
        const next = formik.values.values.map((v) =>
            v.companyId === companyId ? { ...v, waterUsage } : v
        )
        formik.setFieldValue('values', next)
    }

    const handleSubmitExcel = () => {
        const waterRate = Number(formik.values.waterRate)
        const dueDays = Number(formik.values.dueDays)
        if (waterRate < 0 || dueDays < 0) {
            toast.error('نرخ آب و تعداد روز مهلت را وارد کنید')
            return
        }
        if (!excelFile) {
            toast.error('فایل اکسل را انتخاب کنید')
            return
        }
        createBillWithExcel.mutate(
            { waterRate, dueDays, file: excelFile },
            {
                onSuccess: () => {
                    toast.success('قبض آب با موفقیت از طریق اکسل ثبت شد')
                    navigate(Pages.bill.list)
                },
                onError: (error: ErrorType) => {
                    toast.error(error.response?.data?.error?.message?.[0] ?? 'خطا در ثبت قبض با اکسل')
                },
            }
        )
    }

    return (
        <div className="mt-4">
            <div className="flex justify-between items-center flex-wrap gap-3">
                <div className="text-lg font-medium">افزودن قبض آب</div>
                <div className="flex items-center gap-2 flex-wrap">
                    <Button
                        className="w-fit px-4"
                        onClick={() => formik.handleSubmit()}
                        isLoading={createBill.isPending}
                    >
                        <div className="flex items-center gap-2">
                            <TickCircle size={20} color="white" />
                            <span>ثبت قبض</span>
                        </div>
                    </Button>
                    <div
                        {...getRootProps()}
                        className="flex items-center gap-2 border border-border border-dashed rounded-xl pl-2 pr-1 py-1 bg-gray-50 min-h-10 cursor-pointer hover:bg-gray-100 transition-colors"
                    >
                        <input {...getInputProps()} />
                        <div className="flex items-center gap-2 text-sm text-gray-600 whitespace-nowrap pointer-events-none">
                            <DocumentUpload size={18} className="shrink-0" />
                            <span>فایل اکسل</span>
                        </div>
                        {excelFile ? (
                            <span className="text-xs text-gray-700 max-w-[140px] truncate pointer-events-none" title={excelFile.name}>
                                {excelFile.name}
                            </span>
                        ) : (
                            <span className="text-xs text-gray-400 pointer-events-none">کلیک یا فایل را اینجا رها کنید</span>
                        )}
                        <Button
                            type="button"
                            className="w-fit px-4 bg-secondary text-black hover:bg-secondary/90 shrink-0"
                            onClick={(e) => {
                                e.stopPropagation()
                                handleSubmitExcel()
                            }}
                            isLoading={createBillWithExcel.isPending}
                        >
                            <span>ثبت با اکسل</span>
                        </Button>
                    </div>
                </div>
            </div>

            <div className="mt-10 bg-white py-8 xl:px-10 px-4 rounded-3xl">
                <div className="text-base font-medium mb-6">اطلاعات قبض</div>

                <div className="rowTwoInput mt-6">
                    <Input
                        label="نرخ آب (تومان)"
                        name="waterRate"
                        type="number"
                        min={0}
                        value={formik.values.waterRate}
                        onChange={formik.handleChange}
                        error_text={formik.touched.waterRate && formik.errors.waterRate ? String(formik.errors.waterRate) : ''}
                    />
                    <Input
                        label="تعداد روز مهلت پرداخت"
                        name="dueDays"
                        type="number"
                        min={0}
                        value={formik.values.dueDays}
                        onChange={formik.handleChange}
                        error_text={formik.touched.dueDays && formik.errors.dueDays ? String(formik.errors.dueDays) : ''}
                    />
                </div>

                <div className="mt-8">
                    <div className="mb-4">
                        <span className="text-sm font-medium">مصرف آب به تفکیک شرکت</span>
                        <p className="text-xs text-gray-500 mt-1">مصرف آب هر شرکت را در ردیف مربوطه وارد کنید.</p>
                    </div>

                    <div className="border border-border rounded-2xl overflow-hidden">
                        <table className="w-full text-sm">
                            <thead className="bg-gray-50">
                                <tr>
                                    <th className="text-right py-3 px-4 font-medium border-b border-border">ردیف</th>
                                    <th className="text-right py-3 px-4 font-medium border-b border-border">نام شرکت</th>
                                    <th className="text-right py-3 px-4 font-medium border-b border-border w-48">مصرف آب</th>
                                </tr>
                            </thead>
                            <tbody>
                                {companies.map((company, index) => {
                                    const value = formik.values.values.find((v) => v.companyId === company.id)
                                    const usage = value?.waterUsage ?? 0
                                    return (
                                        <tr key={company.id} className="border-b border-border last:border-0 hover:bg-gray-50/50">
                                            <td className="py-3 px-4 text-gray-600">{index + 1}</td>
                                            <td className="py-3 px-4 font-medium">{company.name}</td>
                                            <td className="py-2 px-4">
                                                <Input
                                                    name={`usage-${company.id}`}
                                                    type="number"
                                                    min={0}
                                                    value={usage}
                                                    onChange={(e) => setWaterUsage(company.id, Number(e.target.value) || 0)}
                                                    error_text={
                                                        Array.isArray(formik.errors.values) &&
                                                            formik.errors.values[index] &&
                                                            (formik.errors.values[index] as { waterUsage?: string })?.waterUsage
                                                            ? (formik.errors.values[index] as { waterUsage: string }).waterUsage
                                                            : ''
                                                    }
                                                    className="!mb-0"
                                                />
                                            </td>
                                        </tr>
                                    )
                                })}
                            </tbody>
                        </table>
                    </div>

                    {formik.touched.values && typeof formik.errors.values === 'string' && (
                        <div className="text-xs text-red-600 mt-2 font-medium">{formik.errors.values}</div>
                    )}
                </div>
            </div>
        </div>
    )
}

export default CreateBill
