import { useCallback, useEffect, useRef, useState } from "react";

import { getProfile, updateProfile, uploadAvatar } from "../api/profile";
import { useAuth } from "../state/auth";
import type { UserProfile } from "../api/profile";

type ProfileStatus = "loading" | "ready" | "error" | "saving";

export const ProfilePage = () => {
  const { refreshSession } = useAuth();
  const [status, setStatus] = useState<ProfileStatus>("loading");
  const [profile, setProfile] = useState<UserProfile | null>(null);
  const [name, setName] = useState("");
  const [email, setEmail] = useState("");
  const [error, setError] = useState<string | null>(null);
  const fileInputRef = useRef<HTMLInputElement>(null);

  const loadProfile = useCallback(async () => {
    setStatus("loading");
    setError(null);
    try {
      const data = await getProfile();
      setProfile(data);
      setName(data.name);
      setEmail(data.email);
      setStatus("ready");
    } catch {
      setProfile(null);
      setStatus("error");
    }
  }, []);

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

  const handleSave = useCallback(async () => {
    if (!name.trim()) {
      setError("Name cannot be empty");
      return;
    }
    if (!email.includes("@")) {
      setError("Please enter a valid email");
      return;
    }

    setStatus("saving");
    setError(null);
    try {
      const updated = await updateProfile({ name: name.trim(), email: email.trim() });
      setProfile(updated);
      await refreshSession();
      setStatus("ready");
    } catch {
      setError("Failed to update profile");
      setStatus("ready");
    }
  }, [name, email, refreshSession]);

  const handleAvatarChange = useCallback(
    async (event: React.ChangeEvent<HTMLInputElement>) => {
      const file = event.target.files?.[0];
      if (!file) return;

      if (!file.type.startsWith("image/")) {
        setError("Please upload an image file (PNG or JPEG)");
        return;
      }

      if (file.size > 2 * 1024 * 1024) {
        setError("File too large. Maximum size is 2MB.");
        return;
      }

      setStatus("saving");
      setError(null);
      try {
        const updated = await uploadAvatar(file);
        setProfile(updated);
        await refreshSession();
        setStatus("ready");
      } catch {
        setError("Failed to upload avatar");
        setStatus("ready");
      }
    },
    [refreshSession]
  );

  const avatarUrl = profile?.avatar_url ?? null;

  return (
    <section className="stack">
      <h1>Profile</h1>

      {status === "loading" && <p className="muted">Loading profile...</p>}

      {status === "error" && (
        <div className="card stack">
          <p>Failed to load profile</p>
          <button className="secondary-button" onClick={() => void loadProfile()} type="button">
            Retry
          </button>
        </div>
      )}

      {(status === "ready" || status === "saving") && profile && (
        <div className="card stack">
          <div className="profile-avatar-section">
            <div className="avatar-preview">
              {avatarUrl ? (
                <img alt="Avatar" className="avatar-image" src={avatarUrl} />
              ) : (
                <div className="avatar-placeholder">{profile.name.charAt(0).toUpperCase()}</div>
              )}
            </div>
            <button
              className="secondary-button"
              disabled={status === "saving"}
              onClick={() => fileInputRef.current?.click()}
              type="button"
            >
              {status === "saving" ? "Uploading..." : "Change Avatar"}
            </button>
            <input
              accept="image/png,image/jpeg"
              onChange={handleAvatarChange}
              ref={fileInputRef}
              style={{ display: "none" }}
              type="file"
            />
          </div>

          <div className="form-group">
            <label htmlFor="profile-name">Name</label>
            <input
              disabled={status === "saving"}
              id="profile-name"
              onChange={(e) => setName(e.target.value)}
              type="text"
              value={name}
            />
          </div>

          <div className="form-group">
            <label htmlFor="profile-email">Email</label>
            <input
              disabled={status === "saving"}
              id="profile-email"
              onChange={(e) => setEmail(e.target.value)}
              type="email"
              value={email}
            />
          </div>

          {error && <p className="error-message">{error}</p>}

          <div className="form-actions">
            <button
              className="primary-button"
              disabled={status === "saving"}
              onClick={() => void handleSave()}
              type="button"
            >
              {status === "saving" ? "Saving..." : "Save Changes"}
            </button>
          </div>
        </div>
      )}
    </section>
  );
};
