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

import { getProfile, updateProfile, uploadAvatar } from "../api/profile";
import { ErrorState, LoadingState } from "../components/data-states";
import { Icon } from "../components/icon";
import { ProfileMobileView } from "../components/features/profile/ProfileMobileView";
import { useAuth } from "../state/auth";
import { useAsyncData } from "../hooks/use-async-data";
import { useMobileViewport } from "../hooks/use-mobile-viewport";
import type { UserProfile } from "../api/profile";

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

export const ProfilePage = () => {
  const isMobile = useMobileViewport();
  const { refreshSession } = useAuth();
  const { data: profile, status: loadStatus, reload } = useAsyncData<UserProfile>(getProfile, []);
  const [displayStatus, setDisplayStatus] = useState<ProfileStatus>("loading");
  const [name, setName] = useState("");
  const [email, setEmail] = useState("");
  const [error, setError] = useState<string | null>(null);
  const fileInputRef = useRef<HTMLInputElement>(null);

  // Sync loaded profile into form fields
  useEffect(() => {
    if (profile) {
      setName(profile.name);
      setEmail(profile.email);
      setDisplayStatus("ready");
      setError(null);
    }
  }, [profile]);

  useEffect(() => {
    if (loadStatus === "error") {
      setDisplayStatus("error");
    }
  }, [loadStatus]);

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

    setDisplayStatus("saving");
    setError(null);
    try {
      await updateProfile({ name: name.trim(), email: email.trim() });
      await refreshSession();
      setDisplayStatus("ready");
    } catch {
      setError("Failed to update profile");
      setDisplayStatus("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;
      }

      setDisplayStatus("saving");
      setError(null);
      try {
        await uploadAvatar(file);
        await refreshSession();
        reload();
        setDisplayStatus("ready");
      } catch {
        setError("Failed to upload avatar");
        setDisplayStatus("ready");
      }
    },
    [refreshSession, reload]
  );

  const avatarUrl = profile?.avatar_url ?? null;

  return (
    <section className="stack">
      {!isMobile && <h1>Profile</h1>}

      {displayStatus === "loading" && <LoadingState message="Loading profile..." />}

      {displayStatus === "error" && <ErrorState message="Failed to load profile" onRetry={reload} />}

      {(displayStatus === "ready" || displayStatus === "saving") && profile && (
        isMobile ? (
          <ProfileMobileView
            profile={profile}
            name={name}
            email={email}
            error={error}
            isSaving={displayStatus === "saving"}
            avatarUrl={avatarUrl}
            fileInputRef={fileInputRef}
            onNameChange={setName}
            onEmailChange={setEmail}
            onAvatarButtonClick={() => fileInputRef.current?.click()}
            onAvatarChange={handleAvatarChange}
            onSave={() => void handleSave()}
          />
        ) : (
          <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={displayStatus === "saving"}
              onClick={() => fileInputRef.current?.click()}
              type="button"
            >
              {displayStatus === "saving" ? (
                <>
                  <Icon name="loading" size="sm" />
                  Uploading...
                </>
              ) : (
                <>
                  <Icon name="edit" size="sm" />
                  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={displayStatus === "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={displayStatus === "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={displayStatus === "saving"}
              onClick={() => void handleSave()}
              type="button"
            >
              {displayStatus === "saving" ? (
                <>
                  <Icon name="loading" size="sm" />
                  Saving...
                </>
              ) : (
                <>
                  <Icon name="save" size="sm" />
                  Save Changes
                </>
              )}
            </button>
          </div>
        </div>
      ))}
    </section>
  );
};
