import { useEffect, useState, useCallback } from 'react'
import { Bell, BellOff, Copy, Plus, Smartphone, Trash2, TriangleAlert } from 'lucide-react'
import type { CaldavCredential, CaldavCredentialCreated } from '../types'
import { fetchCaldavCredentials, createCaldavCredential, deleteCaldavCredential, fetchVapidKey, subscribePush, unsubscribePush } from '../api'

function urlBase64ToUint8Array(base64: string): ArrayBuffer {
  const padding = '='.repeat((4 - (base64.length % 4)) % 4)
  const b64 = (base64 + padding).replace(/-/g, '+').replace(/_/g, '/')
  const raw = atob(b64)
  const buf = new Uint8Array(raw.length)
  for (let i = 0; i < raw.length; i++) buf[i] = raw.charCodeAt(i)
  return buf.buffer
}

type PushState = 'unsupported' | 'denied' | 'off' | 'on' | 'checking'

export default function CalDavSetup() {
  const [credentials, setCredentials] = useState<CaldavCredential[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [label, setLabel] = useState('')
  const [creating, setCreating] = useState(false)
  const [revealed, setRevealed] = useState<CaldavCredentialCreated | null>(null)

  const [pushState, setPushState] = useState<PushState>('checking')
  const [pushBusy, setPushBusy] = useState(false)
  const [pushError, setPushError] = useState<string | null>(null)

  const refreshPushState = useCallback(async () => {
    if (!('serviceWorker' in navigator) || !('PushManager' in window)) {
      setPushState('unsupported')
      return
    }
    if (Notification.permission === 'denied') {
      setPushState('denied')
      return
    }
    try {
      const reg = await navigator.serviceWorker.ready
      const sub = await reg.pushManager.getSubscription()
      setPushState(sub ? 'on' : 'off')
    } catch {
      setPushState('off')
    }
  }, [])

  useEffect(() => { refreshPushState() }, [refreshPushState])

  async function enablePush() {
    setPushBusy(true)
    setPushError(null)
    try {
      const reg = await navigator.serviceWorker.ready
      if (Notification.permission === 'default') {
        const permission = await Notification.requestPermission()
        if (permission !== 'granted') { setPushState('denied'); return }
      } else if (Notification.permission === 'denied') {
        setPushState('denied')
        return
      }
      const { publicKey } = await fetchVapidKey()
      const sub = await reg.pushManager.subscribe({
        userVisibleOnly: true,
        applicationServerKey: urlBase64ToUint8Array(publicKey),
      })
      await subscribePush(sub.toJSON())
      setPushState('on')
    } catch (err) {
      setPushError(err instanceof Error ? err.message : 'Failed to enable push notifications')
    } finally {
      setPushBusy(false)
    }
  }

  async function disablePush() {
    setPushBusy(true)
    setPushError(null)
    try {
      const reg = await navigator.serviceWorker.ready
      const sub = await reg.pushManager.getSubscription()
      if (sub) {
        await unsubscribePush(sub.endpoint)
        await sub.unsubscribe()
      }
      setPushState('off')
    } catch (err) {
      setPushError(err instanceof Error ? err.message : 'Failed to disable push notifications')
    } finally {
      setPushBusy(false)
    }
  }

  const caldavUrl = `${window.location.origin}/calendar/caldav/`

  const reload = useCallback(() => {
    setLoading(true)
    setError(null)
    fetchCaldavCredentials().then(setCredentials).catch(err => setError(err.message)).finally(() => setLoading(false))
  }, [])

  useEffect(() => { reload() }, [reload])

  async function handleCreate() {
    setCreating(true)
    setError(null)
    try {
      const created = await createCaldavCredential(label.trim() || undefined)
      setRevealed(created)
      setLabel('')
      reload()
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to create credential')
    } finally {
      setCreating(false)
    }
  }

  async function handleRevoke(id: number) {
    if (!confirm('Revoke this device? It will stop syncing immediately.')) return
    try {
      await deleteCaldavCredential(id)
      if (revealed?.id === id) setRevealed(null)
      reload()
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to revoke credential')
    }
  }

  function copy(text: string) {
    navigator.clipboard?.writeText(text).catch(() => {})
  }

  return (
    <div className="page" style={{ maxWidth: 760 }}>
      <div className="page-header">
        <h1>Phone Sync</h1>
      </div>

      <div className="card">
        <p style={{ marginTop: 0 }}>
          Subscribe to this calendar from your phone or computer's own calendar app (Apple Calendar,
          Google Calendar, Outlook, …) using <strong>CalDAV</strong>. Once set up, events created here
          show up on your device automatically, and new device-created events sync back — no separate app
          needed.
        </p>
        <p style={{ marginBottom: 0 }}>
          Each device needs its own generated username and password below — never share your normal
          hotel login for this.
        </p>
      </div>

      {error && <div className="error-banner">{error}</div>}

      <div className="section-title">Push notifications</div>
      <div className="card" style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
        {pushState === 'on' ? (
          <Bell size={18} strokeWidth={1.75} color="var(--gold)" />
        ) : (
          <BellOff size={18} strokeWidth={1.75} style={{ color: 'var(--text-mid)' }} />
        )}
        <div style={{ flex: 1 }}>
          <div style={{ fontWeight: 600, fontSize: 13.5 }}>
            {pushState === 'unsupported' && 'Not supported on this device/browser'}
            {pushState === 'denied' && 'Blocked — enable notifications for this site in your browser settings'}
            {pushState === 'checking' && 'Checking status…'}
            {pushState === 'off' && 'Notifications are off on this device'}
            {pushState === 'on' && 'Notifications are on for this device'}
          </div>
          {pushError && <div className="field-hint" style={{ color: 'var(--danger)' }}>{pushError}</div>}
        </div>
        {(pushState === 'off' || pushState === 'on') && (
          <button
            className={`btn btn-sm ${pushState === 'off' ? 'btn-primary' : ''}`}
            onClick={pushState === 'off' ? enablePush : disablePush}
            disabled={pushBusy}
          >
            {pushBusy ? 'Working…' : pushState === 'off' ? 'Enable' : 'Disable'}
          </button>
        )}
      </div>

      <div className="section-title">Your CalDAV devices</div>
      {loading ? (
        <div className="empty-state">Loading…</div>
      ) : credentials.length === 0 ? (
        <div className="empty-state">No devices set up yet.</div>
      ) : (
        <div className="table-wrap">
          <table className="data">
            <thead>
              <tr>
                <th>Label</th>
                <th>Username</th>
                <th>Created</th>
                <th>Last used</th>
                <th></th>
              </tr>
            </thead>
            <tbody>
              {credentials.map(c => (
                <tr key={c.id}>
                  <td>{c.label || '—'}</td>
                  <td>{c.username}</td>
                  <td>{new Date(c.created_at).toLocaleDateString()}</td>
                  <td>{c.last_used_at ? new Date(c.last_used_at).toLocaleString() : 'Never'}</td>
                  <td style={{ textAlign: 'right' }}>
                    <button className="btn-ghost-sm btn-ghost-danger" onClick={() => handleRevoke(c.id)}>
                      <Trash2 size={13} strokeWidth={1.75} /> Revoke
                    </button>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}

      <div className="field-row" style={{ alignItems: 'flex-end', marginTop: 12 }}>
        <div className="field" style={{ flex: 1 }}>
          <label>Device label (optional)</label>
          <input type="text" value={label} onChange={e => setLabel(e.target.value)} placeholder="e.g. Sarah's iPhone" />
        </div>
        <button className="btn btn-primary" onClick={handleCreate} disabled={creating} style={{ marginBottom: 12 }}>
          <Plus size={14} strokeWidth={1.75} />
          {creating ? 'Generating…' : 'Generate new'}
        </button>
      </div>

      {revealed && (
        <div className="card" style={{ borderColor: 'var(--gold)' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, color: 'var(--danger)', fontWeight: 600, marginBottom: 8 }}>
            <TriangleAlert size={16} strokeWidth={1.75} />
            Save this now — the password won't be shown again.
          </div>
          <div className="cal-credential-box">
            <div>Username: {revealed.username} <Copy size={13} strokeWidth={1.75} style={{ cursor: 'pointer', verticalAlign: 'middle' }} onClick={() => copy(revealed.username)} /></div>
            <div>Password: {revealed.password} <Copy size={13} strokeWidth={1.75} style={{ cursor: 'pointer', verticalAlign: 'middle' }} onClick={() => copy(revealed.password)} /></div>
            <div>Server URL: {caldavUrl} <Copy size={13} strokeWidth={1.75} style={{ cursor: 'pointer', verticalAlign: 'middle' }} onClick={() => copy(caldavUrl)} /></div>
          </div>
          <button className="btn btn-sm" onClick={() => setRevealed(null)}>I've saved it, hide this</button>
        </div>
      )}

      <div className="section-title">Set-up instructions</div>

      <div className="card">
        <div style={{ fontWeight: 600, marginBottom: 6, display: 'flex', alignItems: 'center', gap: 6 }}>
          <Smartphone size={15} strokeWidth={1.75} /> Apple Calendar (iPhone / Mac)
        </div>
        <ol style={{ marginTop: 0, paddingLeft: 20 }}>
          <li>Settings → Calendar → Accounts → Add Account → Other → Add CalDAV Account.</li>
          <li>Server: <code>{caldavUrl}</code></li>
          <li>User Name / Password: the credentials generated above.</li>
          <li>Tap Next, then Save.</li>
        </ol>
      </div>

      <div className="card">
        <div style={{ fontWeight: 600, marginBottom: 6, display: 'flex', alignItems: 'center', gap: 6 }}>
          <Smartphone size={15} strokeWidth={1.75} /> Google Calendar
        </div>
        <ol style={{ marginTop: 0, paddingLeft: 20 }}>
          <li>Google Calendar doesn't support direct CalDAV subscriptions on the free tier — easiest is to
            use a CalDAV-sync app such as "CalDAV-Sync" (Android) with the server URL and credentials above.</li>
          <li>Alternatively, on desktop, add it as a "secondary" calendar in a CalDAV-aware client and it
            will appear alongside Google Calendar.</li>
        </ol>
      </div>

      <div className="card">
        <div style={{ fontWeight: 600, marginBottom: 6, display: 'flex', alignItems: 'center', gap: 6 }}>
          <Smartphone size={15} strokeWidth={1.75} /> Outlook
        </div>
        <ol style={{ marginTop: 0, paddingLeft: 20 }}>
          <li>Outlook (desktop): File → Account Settings → Internet Calendars → New, then paste <code>{caldavUrl}</code>.</li>
          <li>When prompted, enter the username and password generated above.</li>
        </ol>
      </div>
    </div>
  )
}
