import React, { useEffect, useState } from "react";
import {
  Table,
  Button,
  Form,
  Input,
  Select,
  Popconfirm,
  Col,
  Row,
  Card,
  Pagination,
  Typography,
} from "antd";
import { Plus, Edit, Trash2, Search, ShieldCheck } from "lucide-react";
import {
  useForm,
  Controller,
  type SubmitHandler,
  Resolver,
} from "react-hook-form";
import * as yup from "yup";
import { yupResolver } from "@hookform/resolvers/yup";
import type { ColumnsType } from "antd/es/table";
import { API_Instance } from "../../api/axios.instance";
import API_Constants from "../../constants/api.constants";
import {
  institutionPermissionsList,
  IOptionsList,
  IRole,
  staffPermissionsList,
} from "@/types";
import toast from "react-hot-toast";
import { getAxiosErrorMessage } from "@/utils/index.utils";
import Modal from "@/components/shared/Modal";
import { useDebounce } from "@/hooks/useDebounce";
import { useAuth } from "@/hooks/useAuth";

type RoleFormValues = Omit<IRole, "id">;

const schema = yup.object({
  roleName: yup.string().required("Role Name is required"),
  permissions: yup
    .array()
    .of(yup.string())
    .min(1, "At least one permission is required"),
});

const RolesManagement: React.FC = () => {
  const { isInstitution } = useAuth();

  const [roles, setRoles] = useState<IRole[]>([]);
  const [loading, setLoading] = useState(false);
  const [isModalOpen, setIsModalOpen] = useState(false);
  const [editingRole, setEditingRole] = useState<IRole | null>(null);
  const [options, setOptions] = useState<IOptionsList>({
    permissions: Object.values(
      isInstitution ? institutionPermissionsList : staffPermissionsList,
    ).map((value) => ({
      label: value.replace(/([A-Z])/g, " $1").trim(),
      value: value,
    })),
  });
  const [search, setSearch] = useState("");
  const [page, setPage] = useState(1);
  const [limit, setLimit] = useState(10);
  const [total, setTotal] = useState(0);
  const debouncedSearch = useDebounce(search, 600);

  const resolver = yupResolver(schema) as unknown as Resolver<RoleFormValues>;

  const {
    control,
    handleSubmit,
    reset,
    formState: { errors, isSubmitting },
  } = useForm<RoleFormValues>({
    resolver,
    defaultValues: {
      roleName: "",
      permissions: [],
    },
  });

  const buildQuery = (search: string, page: number, limit: number) => {
    const params = new URLSearchParams();
    params.append("page", page.toString());
    params.append("limit", limit.toString());
    if (search) params.append("search", search);
    return params.toString();
  };

  const fetchRoles = async (p = page, l = limit, s = search) => {
    setLoading(true);
    try {
      const res = await API_Instance.get(
        `${API_Constants.roles}?${buildQuery(s, p, l)}`,
      );
      setRoles(res.data.data);
      setTotal(res.data.meta.total);
      setPage(res.data.meta.page);
      setLimit(res.data.meta.limit);
    } catch (error) {
      toast.error(getAxiosErrorMessage(error));
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    fetchRoles(page, limit, debouncedSearch);
  }, [page, limit, debouncedSearch]);

  const openModal = (role: IRole | null = null) => {
    setEditingRole(role);
    reset({
      roleName: role?.roleName || "",
      permissions: role?.permissions || [],
    });
    setIsModalOpen(true);
  };

  const closeModal = () => {
    setEditingRole(null);
    setIsModalOpen(false);
    reset();
  };

  const onFormSubmit: SubmitHandler<RoleFormValues> = async (data) => {
    try {
      if (editingRole) {
        await API_Instance.put(
          `${API_Constants.roles}/${editingRole.id}`,
          data,
        );
        toast.success("Role updated successfully");
      } else {
        await API_Instance.post(API_Constants.roles, data);
        toast.success("Role added successfully");
      }
      fetchRoles();
    } catch (err) {
      toast.error(getAxiosErrorMessage(err));
    } finally {
      closeModal();
    }
  };

  const handleDelete = async (id: string) => {
    try {
      await API_Instance.delete(`${API_Constants.roles}/${id}`);
      toast.success("Role deleted successfully");
      fetchRoles();
    } catch (err) {
      toast.error(getAxiosErrorMessage(err));
    }
  };

  const columns: ColumnsType<IRole> = [
    {
      title: "Role Name",
      dataIndex: "roleName",
      key: "roleName",
      render: (text) => (
        <span className="font-medium text-slate-700">{text}</span>
      ),
    },
    {
      title: "Permissions",
      key: "permissions",
      dataIndex: "permissions",
      render: (permissions: string[] = []) => (
        <div className="flex flex-wrap gap-1">
          {permissions
            .sort((a, b) => a.localeCompare(b))
            .map((perm) => (
              <span
                key={perm}
                className="px-2 py-0.5 text-xs bg-blue-50 text-blue-600 rounded-full border border-blue-100"
              >
                {perm.replace(/([A-Z])/g, " $1").trim()}
              </span>
            ))}
        </div>
      ),
    },
    {
      title: "Actions",
      key: "actions",
      width: 120,
      render: (_, record) => (
        <div className="flex space-x-2">
          <button
            onClick={() => openModal(record)}
            className="text-[#1677ff] hover:text-[#579af8]"
          >
            <Edit className="h-5 w-5" />
          </button>
          <Popconfirm
            title="Delete role?"
            onConfirm={() => handleDelete(record.id)}
            okText="Yes"
            cancelText="No"
          >
            <button className="text-red-600 hover:text-red-800">
              <Trash2 className="h-5 w-5" />
            </button>
          </Popconfirm>
        </div>
      ),
    },
  ];

  const handleSelectAll = (
    value: string[],
    onChange: any,
    allOptions: any[],
  ) => {
    if (value.includes("all")) {
      const alreadyAllSelected = value.length > allOptions.length;
      if (alreadyAllSelected) {
        onChange([]);
      } else {
        onChange(allOptions.map((opt) => opt.value));
      }
    } else {
      onChange(value);
    }
  };

  return (
    <div className="flex flex-col gap-4 px-4 py-6">
      <div className="flex flex-col md:flex-row justify-between items-start md:items-center gap-4">
        <div>
          <h2 className="text-2xl font-bold text-slate-800 flex items-center gap-2">
            <ShieldCheck className="text-blue-600" /> Role Management
          </h2>
          <p className="text-slate-500 text-sm mt-1">
            Add/Manage Roles & Permissions.
          </p>
        </div>
        <Button
          type="primary"
          icon={<Plus size={16} />}
          onClick={() => openModal()}
        >
          Add New Role
        </Button>
      </div>

      <Card className="shadow-sm border border-slate-200 rounded-xl">
        <div className="flex flex-col md:flex-row justify-between items-center gap-4 mb-4">
          <Input
            placeholder={"Search roles..."}
            prefix={<Search size={16} className="text-slate-400" />}
            className="w-full md:w-72"
            allowClear
            autoComplete="off"
            onChange={(e) => setSearch(e.target.value)}
          />
          <div className="text-slate-500 text-sm">
            Total:{" "}
            <span className="font-semibold text-slate-800">
              {total}
            </span>
          </div>
        </div>

        <Table
          columns={columns}
          dataSource={roles}
          loading={loading}
          pagination={false}
          rowKey="id"
          scroll={{ x: 600 }}
          className="border border-slate-100 rounded-lg overflow-hidden"
        />

        <div className="flex justify-end mt-4">
          <Pagination
            current={page}
            total={total}
            pageSize={limit}
            onChange={(p, pageSize) => {
              setPage(p);
              setLimit(pageSize);
            }}
            showSizeChanger
            showTotal={(total) => `Total ${total} items`}
          />
        </div>
      </Card>

      <Modal
        isOpen={isModalOpen}
        onClose={closeModal}
        title={editingRole ? "Edit Role" : "Add Role"}
      >
        <Form layout="vertical" onFinish={handleSubmit(onFormSubmit)}>
          <Form.Item
            label="Role Name"
            validateStatus={errors.roleName ? "error" : ""}
            help={errors.roleName?.message}
            required
          >
            <Controller
              name="roleName"
              control={control}
              render={({ field }) => (
                <Input
                  {...field}
                  placeholder="Enter role name (e.g. Content Manager)"
                />
              )}
            />
          </Form.Item>

          <Form.Item
            label="Permissions"
            validateStatus={errors.permissions ? "error" : ""}
            help={errors.permissions?.message}
            required
          >
            <Controller
              name="permissions"
              control={control}
              render={({ field }) => (
                <Select
                  mode="multiple"
                  value={field.value || []}
                  placeholder="Select Permissions"
                  options={[
                    { value: "all", label: "Select All" },
                    ...options.permissions,
                  ]}
                  onChange={(value) =>
                    handleSelectAll(value, field.onChange, options.permissions)
                  }
                />
              )}
            />
          </Form.Item>

          <div className="flex justify-end gap-3 mt-4">
            <Button onClick={closeModal}>Cancel</Button>
            <Button type="primary" htmlType="submit" loading={isSubmitting}>
              Save Role
            </Button>
          </div>
        </Form>
      </Modal>
    </div>
  );
};

export default RolesManagement;

