import React, { useMemo } from 'react';
import { Accordion, Badge, Col, Form, Row } from 'react-bootstrap';
import type { UserRole } from '../../../../types/auth';

interface Option {
    value: number;
    label: string;
}

export interface UserAccessFormData {
    role: UserRole;
    is_active: boolean;
    contact_id: number | '';
    comercializadora_id: number | '';
    permissions: string[];
}

interface Props {
    data: UserAccessFormData;
    setData: (field: keyof UserAccessFormData, value: UserAccessFormData[keyof UserAccessFormData]) => void;
    errors: Partial<Record<string, string>>;
    permissionGroups: Record<string, Record<string, string>>;
    roleDefaults: Record<UserRole, string[]>;
    assignableRoles: UserRole[];
    contactOptions: Option[];
    comercializadoraOptions: Option[];
}

const ROLE_LABELS: Record<UserRole, string> = {
    super_admin: 'Super administrador',
    admin: 'Administrador',
    user: 'Estándar',
    colaborador: 'Colaborador',
    prescriptor: 'Prescriptor',
    comercializadora: 'Comercializadora',
};

export const UserAccessFields = ({
    data,
    setData,
    errors,
    permissionGroups,
    roleDefaults,
    assignableRoles,
    contactOptions,
    comercializadoraOptions,
}: Props) => {
    const inherited = useMemo(
        () => new Set(roleDefaults[data.role] ?? []),
        [data.role, roleDefaults],
    );
    const additional = useMemo(() => new Set(data.permissions), [data.permissions]);

    const changeRole = (role: UserRole) => {
        setData('role', role);
        setData('contact_id', '');
        setData('comercializadora_id', '');
        setData('permissions', []);
    };

    const togglePermission = (permission: string, checked: boolean) => {
        const next = new Set(additional);
        checked ? next.add(permission) : next.delete(permission);
        setData('permissions', Array.from(next));
    };

    return (
        <>
            <Row>
                <Col md={6} className="mb-3">
                    <Form.Group>
                        <Form.Label>Rol <span className="text-danger">*</span></Form.Label>
                        <Form.Select
                            id="user-role-select"
                            value={data.role}
                            onChange={(event) => changeRole(event.target.value as UserRole)}
                            isInvalid={Boolean(errors.role)}
                        >
                            {assignableRoles.map((role) => (
                                <option key={role} value={role}>{ROLE_LABELS[role]}</option>
                            ))}
                        </Form.Select>
                        <Form.Control.Feedback type="invalid">{errors.role}</Form.Control.Feedback>
                    </Form.Group>
                </Col>

                <Col md={6} className="mb-3 d-flex align-items-center">
                    <Form.Check
                        type="switch"
                        id="user-is-active"
                        label="Usuario activo"
                        checked={data.is_active}
                        onChange={(event) => setData('is_active', event.target.checked)}
                    />
                </Col>

                {['colaborador', 'prescriptor'].includes(data.role) && (
                    <Col md={6} className="mb-3">
                        <Form.Group>
                            <Form.Label>Contacto asociado <span className="text-danger">*</span></Form.Label>
                            <Form.Select
                                id="user-contact-select"
                                value={data.contact_id}
                                onChange={(event) => setData('contact_id', Number(event.target.value) || '')}
                                isInvalid={Boolean(errors.contact_id)}
                            >
                                <option value="">Selecciona un contacto</option>
                                {contactOptions.map((option) => (
                                    <option key={option.value} value={option.value}>{option.label}</option>
                                ))}
                            </Form.Select>
                            <Form.Control.Feedback type="invalid">{errors.contact_id}</Form.Control.Feedback>
                        </Form.Group>
                    </Col>
                )}

                {data.role === 'comercializadora' && (
                    <Col md={6} className="mb-3">
                        <Form.Group>
                            <Form.Label>Comercializadora asociada <span className="text-danger">*</span></Form.Label>
                            <Form.Select
                                id="user-comercializadora-select"
                                value={data.comercializadora_id}
                                onChange={(event) => setData('comercializadora_id', Number(event.target.value) || '')}
                                isInvalid={Boolean(errors.comercializadora_id)}
                            >
                                <option value="">Selecciona una comercializadora</option>
                                {comercializadoraOptions.map((option) => (
                                    <option key={option.value} value={option.value}>{option.label}</option>
                                ))}
                            </Form.Select>
                            <Form.Control.Feedback type="invalid">{errors.comercializadora_id}</Form.Control.Feedback>
                        </Form.Group>
                    </Col>
                )}
            </Row>

            <Form.Group className="mt-2">
                <div className="d-flex justify-content-between align-items-center mb-2">
                    <Form.Label className="mb-0">Permisos</Form.Label>
                    <small className="text-muted">Los heredados del rol están marcados; puedes añadir excepciones.</small>
                </div>
                <Accordion alwaysOpen>
                    {Object.entries(permissionGroups).map(([group, permissions], groupIndex) => (
                        <Accordion.Item eventKey={String(groupIndex)} key={group}>
                            <Accordion.Header>{group}</Accordion.Header>
                            <Accordion.Body>
                                <Row>
                                    {Object.entries(permissions).map(([permission, label]) => {
                                        const isInherited = inherited.has(permission);
                                        return (
                                            <Col md={6} xl={4} className="mb-2" key={permission}>
                                                <Form.Check
                                                    id={`permission-${permission.replaceAll('.', '-')}`}
                                                    checked={isInherited || additional.has(permission)}
                                                    disabled={isInherited}
                                                    onChange={(event) => togglePermission(permission, event.target.checked)}
                                                    label={(
                                                        <>
                                                            {label}
                                                            {isInherited && <Badge bg="light" text="dark" className="ms-2">Rol</Badge>}
                                                        </>
                                                    )}
                                                />
                                            </Col>
                                        );
                                    })}
                                </Row>
                            </Accordion.Body>
                        </Accordion.Item>
                    ))}
                </Accordion>
            </Form.Group>
        </>
    );
};
