import React, { useEffect, useMemo, useState } from "react";

import {
  Box,
  Button,
  Checkbox,
  FormControlLabel,
  Paper,
  Table,
  TableBody,
  TableCell,
  TableContainer,
  TableHead,
  TableRow,
  TextField,
  Typography,
} from "@mui/material";

import { api } from "../api";
import { useToast } from "../toast";

type UserDto = {
  id: string;
  email?: string | null;
  userName?: string | null;
  emailConfirmed: boolean;
  roles: string[];
};

export default function AdminUsersPage() {
  const { toast } = useToast();
  const [users, setUsers] = useState<UserDto[]>([]);
  const [loading, setLoading] = useState(false);

  const [newEmail, setNewEmail] = useState("");
  const [newPassword, setNewPassword] = useState("");
  const [newIsAdmin, setNewIsAdmin] = useState(false);

  const [testEmailTo, setTestEmailTo] = useState("");
  const [testEmailSubject, setTestEmailSubject] = useState("Job Tracker SMTP test");
  const [testEmailMessage, setTestEmailMessage] = useState("This is a test email from the Job Tracker admin panel.");
  const [sendingTestEmail, setSendingTestEmail] = useState(false);

  async function load() {
    setLoading(true);
    try {
      const res = await api.get<UserDto[]>("/users");
      setUsers(res.data ?? []);
    } catch {
      setUsers([]);
    } finally {
      setLoading(false);
    }
  }

  useEffect(() => {
    void load();
  }, []);

  const canCreate = useMemo(() => newEmail.trim().length > 3 && newPassword.length >= 6, [newEmail, newPassword]);

  const setAdminRole = async (u: UserDto, isAdmin: boolean) => {
    try {
      await api.put(`/users/${u.id}/roles`, { roles: isAdmin ? ["Admin"] : [] });
      toast("Roles updated.", "success");
      await load();
    } catch (e: any) {
      const msg = e?.response?.data || e?.message || "Failed to update roles.";
      toast(String(msg), "error");
    }
  };

  const sendReset = async (u: UserDto) => {
    try {
      await api.post(`/users/${u.id}/send-password-reset`);
      toast("Password reset email sent.", "success");
    } catch (e: any) {
      const msg = e?.response?.data || e?.message || "Failed to send reset.";
      toast(String(msg), "error");
    }
  };

  const sendTestEmail = async () => {
    setSendingTestEmail(true);
    try {
      await api.post("/users/send-test-email", {
        toEmail: testEmailTo.trim() || null,
        subject: testEmailSubject.trim() || null,
        message: testEmailMessage.trim() || null,
      });
      toast("Test email sent.", "success");
    } catch (e: any) {
      const msg = e?.response?.data || e?.message || "Failed to send test email.";
      toast(String(msg), "error");
    } finally {
      setSendingTestEmail(false);
    }
  };

  const remove = async (u: UserDto) => {
    if (!confirmAction(`Delete user ${u.email || u.userName || u.id}?`)) return;
    try {
      await api.delete(`/users/${u.id}`);
      toast("User deleted.", "info");
      await load();
    } catch {
      toast("Failed to delete user.", "error");
    }
  };

  return (
    <Paper sx={{ p: 2 }}>
      <Typography variant="h6" sx={{ fontWeight: 950, mb: 0.5 }}>
        Users
      </Typography>
      <Typography sx={{ color: "text.secondary", mb: 2 }}>Admin-only user management.</Typography>

      <Paper sx={{ p: 2, mb: 2 }}>
        <Typography sx={{ fontWeight: 900, mb: 1 }}>SMTP test email</Typography>
        <Typography variant="body2" sx={{ color: "text.secondary", mb: 1.5 }}>
          Send a quick delivery check using the configured SMTP settings. Leave the recipient blank to use your admin email.
        </Typography>
        <Box sx={{ display: "grid", gridTemplateColumns: { xs: "1fr", md: "1fr 1fr" }, gap: 1.5 }}>
          <TextField
            label="Recipient email"
            value={testEmailTo}
            onChange={(e) => setTestEmailTo(e.target.value)}
            placeholder="Uses your admin email if left blank"
          />
          <TextField label="Subject" value={testEmailSubject} onChange={(e) => setTestEmailSubject(e.target.value)} />
          <TextField
            label="Message"
            multiline
            minRows={3}
            value={testEmailMessage}
            onChange={(e) => setTestEmailMessage(e.target.value)}
            sx={{ gridColumn: { xs: "1 / -1", md: "1 / -1" } }}
          />
        </Box>
        <Box sx={{ display: "flex", justifyContent: "flex-end", mt: 1.5 }}>
          <Button variant="contained" disabled={sendingTestEmail} onClick={() => void sendTestEmail()}>
            {sendingTestEmail ? "Sending..." : "Send test email"}
          </Button>
        </Box>
      </Paper>

      <Paper sx={{ p: 2, mb: 2 }}>
        <Typography sx={{ fontWeight: 900, mb: 1 }}>Create user</Typography>
        <Box sx={{ display: "grid", gridTemplateColumns: { xs: "1fr", md: "1fr 1fr" }, gap: 1.5 }}>
          <TextField label="Email" value={newEmail} onChange={(e) => setNewEmail(e.target.value)} />
          <TextField label="Password" type="password" value={newPassword} onChange={(e) => setNewPassword(e.target.value)} />
        </Box>
        <Box sx={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 2, mt: 1.5, flexWrap: "wrap" }}>
          <FormControlLabel control={<Checkbox checked={newIsAdmin} onChange={(e) => setNewIsAdmin(e.target.checked)} />} label="Admin" />
          <Button
            variant="contained"
            disabled={!canCreate || loading}
            onClick={async () => {
              try {
                await api.post("/users", { email: newEmail, password: newPassword, roles: newIsAdmin ? ["Admin"] : [] });
                setNewEmail("");
                setNewPassword("");
                setNewIsAdmin(false);
                toast("User created.", "success");
                await load();
              } catch (e: any) {
                const msg = e?.response?.data || e?.message || "Failed to create user.";
                toast(String(msg), "error");
              }
            }}
          >
            Create
          </Button>
        </Box>
      </Paper>

      <TableContainer sx={{ borderRadius: 2, border: "1px solid", borderColor: "divider" }}>
        <Table size="small">
          <TableHead>
            <TableRow>
              <TableCell>Email</TableCell>
              <TableCell>Username</TableCell>
              <TableCell>Roles</TableCell>
              <TableCell>Confirmed</TableCell>
              <TableCell align="right">Actions</TableCell>
            </TableRow>
          </TableHead>
          <TableBody>
            {users.map((u) => {
              const isAdmin = (u.roles || []).includes("Admin");
              return (
                <TableRow key={u.id} hover>
                  <TableCell sx={{ fontWeight: 850 }}>{u.email || ""}</TableCell>
                  <TableCell sx={{ color: "text.secondary" }}>{u.userName || ""}</TableCell>
                  <TableCell sx={{ color: "text.secondary" }}>{u.roles?.length ? u.roles.join(", ") : "-"}</TableCell>
                  <TableCell sx={{ color: "text.secondary" }}>{u.emailConfirmed ? "Yes" : "No"}</TableCell>
                  <TableCell align="right">
                    <Box sx={{ display: "flex", justifyContent: "flex-end", gap: 1, flexWrap: "wrap" }}>
                      <Button size="small" variant={isAdmin ? "contained" : "outlined"} onClick={() => void setAdminRole(u, !isAdmin)}>
                        Admin
                      </Button>
                      <Button size="small" variant="outlined" onClick={() => void sendReset(u)}>
                        Send reset
                      </Button>
                      <Button size="small" color="error" variant="outlined" onClick={() => void remove(u)}>
                        Delete
                      </Button>
                    </Box>
                  </TableCell>
                </TableRow>
              );
            })}

            {!loading && users.length === 0 ? (
              <TableRow>
                <TableCell colSpan={5}>
                  <Typography sx={{ color: "text.secondary", py: 2, textAlign: "center" }}>No users.</Typography>
                </TableCell>
              </TableRow>
            ) : null}
          </TableBody>
        </Table>
      </TableContainer>
    </Paper>
  );
}
