import { FormEvent, useCallback, useEffect, useState } from 'react';
import Layout from '../../components/Layout';
import { api } from '../../lib/api';
import { useRequireAuth } from '../../lib/auth-context';

interface DeviceRow {
  id: string;
  name: string;
  serialNumber: string | null;
  mqttUsername: string | null;
  isActive: boolean;
  disabledReason: string | null;
  lastSeenAt: string | null;
}

export default function DevicesPage() {
  const { user, activeOrg, loading } = useRequireAuth();
  const orgId = activeOrg?.org.id ?? null;
  const isAdmin = activeOrg?.role === 'ORG_ADMIN';

  const [devices, setDevices] = useState<DeviceRow[]>([]);
  const [form, setForm] = useState({ name: '', mqttUsername: '', serialNumber: '' });
  const [disablingId, setDisablingId] = useState<string | null>(null);
  const [disableReason, setDisableReason] = useState('');
  const [notice, setNotice] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);

  const reload = useCallback(() => {
    if (!orgId) {
      return;
    }
    api
      .get<DeviceRow[]>(`/api/orgs/${orgId}/devices`)
      .then((rows) => {
        setDevices(rows);
        setError(null);
      })
      .catch((err) => setError(err.message));
  }, [orgId]);

  useEffect(reload, [reload]);

  const addDevice = async (e: FormEvent) => {
    e.preventDefault();
    try {
      const created = await api.post<DeviceRow & { provisioning: { pointsTopic?: string; note: string } }>(
        `/api/orgs/${orgId}/devices`,
        {
          name: form.name,
          mqttUsername: form.mqttUsername || undefined,
          serialNumber: form.serialNumber || undefined,
        },
      );
      setNotice(
        created.provisioning.pointsTopic
          ? `Device created. It should publish points to ${created.provisioning.pointsTopic}`
          : created.provisioning.note,
      );
      setForm({ name: '', mqttUsername: '', serialNumber: '' });
      reload();
    } catch (err: any) {
      setError(err.message);
    }
  };

  const enable = async (deviceId: string) => {
    try {
      await api.patch(`/api/orgs/${orgId}/devices/${deviceId}`, { isActive: true });
      reload();
    } catch (err: any) {
      setError(err.message);
    }
  };

  const confirmDisable = async (deviceId: string) => {
    try {
      await api.patch(`/api/orgs/${orgId}/devices/${deviceId}`, {
        isActive: false,
        disabledReason: disableReason || undefined,
      });
      setDisablingId(null);
      setDisableReason('');
      reload();
    } catch (err: any) {
      setError(err.message);
    }
  };

  const remove = async (deviceId: string) => {
    try {
      await api.delete(`/api/orgs/${orgId}/devices/${deviceId}`);
      reload();
    } catch (err: any) {
      setError(err.message);
    }
  };

  if (loading || !user) {
    return null;
  }

  return (
    <Layout title="Devices">
      <h1>Devices</h1>
      <p style={{ color: '#666' }}>
        Field devices publish to <code>devices/&lt;mqtt username&gt;/points</code>. Broker credentials are provisioned
        separately for now. A disabled device can check <code>GET /api/devices/&lt;serial&gt;/status</code> for its
        disabled state and reason.
      </p>
      {error && <p style={{ color: '#c62828' }}>{error}</p>}
      {notice && <p style={{ color: '#388e3c' }}>{notice}</p>}

      {isAdmin && (
        <form onSubmit={addDevice} style={{ display: 'flex', gap: '0.5rem', marginBottom: '1.5rem', flexWrap: 'wrap' }}>
          <input
            placeholder="name"
            value={form.name}
            onChange={(e) => setForm((f) => ({ ...f, name: e.target.value }))}
            required
            style={{ padding: '0.4rem' }}
          />
          <input
            placeholder="serial number"
            value={form.serialNumber}
            onChange={(e) => setForm((f) => ({ ...f, serialNumber: e.target.value }))}
            style={{ padding: '0.4rem' }}
          />
          <input
            placeholder="mqtt username (only if it connects itself)"
            value={form.mqttUsername}
            onChange={(e) => setForm((f) => ({ ...f, mqttUsername: e.target.value }))}
            style={{ padding: '0.4rem' }}
          />
          <button type="submit">Add device</button>
        </form>
      )}

      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead>
          <tr style={{ textAlign: 'left', borderBottom: '2px solid #ddd' }}>
            <th style={{ padding: '0.5rem' }}>Name</th>
            <th>MQTT username</th>
            <th>Serial</th>
            <th>Status</th>
            <th>Last seen</th>
            {isAdmin && <th />}
          </tr>
        </thead>
        <tbody>
          {devices.map((d) => (
            <tr key={d.id} style={{ borderBottom: '1px solid #eee' }}>
              <td style={{ padding: '0.5rem' }}>{d.name}</td>
              <td>{d.mqttUsername ? <code>{d.mqttUsername}</code> : '—'}</td>
              <td>{d.serialNumber ?? '—'}</td>
              <td style={{ color: d.isActive ? '#388e3c' : '#c62828' }}>
                {d.isActive ? 'active' : 'disabled'}
                {!d.isActive && d.disabledReason && (
                  <div style={{ color: '#888', fontWeight: 400, fontSize: '0.85rem' }}>{d.disabledReason}</div>
                )}
              </td>
              <td>{d.lastSeenAt ? new Date(d.lastSeenAt).toLocaleString() : 'never'}</td>
              {isAdmin && (
                <td style={{ textAlign: 'right', whiteSpace: 'nowrap' }}>
                  {d.isActive ? (
                    <button onClick={() => setDisablingId(d.id)}>Disable</button>
                  ) : (
                    <button onClick={() => enable(d.id)}>Enable</button>
                  )}{' '}
                  <button onClick={() => remove(d.id)}>Delete</button>
                </td>
              )}
            </tr>
          ))}
          {isAdmin &&
            disablingId &&
            devices.some((d) => d.id === disablingId) && (
              <tr>
                <td colSpan={6} style={{ padding: '0.75rem', background: '#fff8f8' }}>
                  <form
                    onSubmit={(e) => {
                      e.preventDefault();
                      confirmDisable(disablingId);
                    }}
                    style={{ display: 'flex', gap: '0.5rem', alignItems: 'center' }}
                  >
                    <span>Reason for disabling {devices.find((d) => d.id === disablingId)?.name}:</span>
                    <input
                      autoFocus
                      placeholder="e.g. reported lost, billing hold"
                      value={disableReason}
                      onChange={(e) => setDisableReason(e.target.value)}
                      style={{ padding: '0.4rem', flex: 1 }}
                    />
                    <button type="submit">Confirm disable</button>
                    <button
                      type="button"
                      onClick={() => {
                        setDisablingId(null);
                        setDisableReason('');
                      }}
                    >
                      Cancel
                    </button>
                  </form>
                </td>
              </tr>
            )}
        </tbody>
      </table>
    </Layout>
  );
}
