import { useState, type FormEventHandler } from "react";
import Icon, { ICONS } from "./Icon";
import Modal from "./Modal";
import { useLocation, useNavigate } from "react-router";
import { API } from "~/api/api";
import { useAuth } from "~/context/AuthContext";

export default function Header() {
  const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);

  const { user, login, logout, isLoading } = useAuth();

  const navigate = useNavigate();

  const onBack = () => { navigate("/") };
  const onUploadClick= () => setIsUploadModalOpen(true)

  const [isLoginModalOpen, setIsLoginModalOpen] = useState(false);
  const [isRegisterModalOpen, setIsRegisterModalOpen] = useState(false);
  const [isUploadModalOpen, setIsUploadModalOpen] = useState(false);

  const onTagsClick = () => { navigate("/tags") }
  const onLoginClick = () => { setIsLoginModalOpen(true); }
  const onRegisterClick = () => { setIsRegisterModalOpen(true); }

  const onLogout = () => { logout(); if(isMobileMenuOpen) setIsMobileMenuOpen(false); }

  type NavButtonProps = {
    onClick: () => void;
    icon: string;
    children: React.ReactNode;
    className?: string;
  };

  const NavButton = ({ onClick, icon, children, className = '' }: NavButtonProps) => (
    <button onClick={onClick} className={`flex items-center space-x-2 px-4 py-2 font-semibold rounded-lg transition-colors ${className}`}>
      <Icon path={icon} />
      <span className="hidden md:inline">{children}</span>
    </button>
  );
    
  type MobileNavLinkProps = {
    onClick: () => void;
    icon: string;
    children: React.ReactNode;
    className?: string;
  };

  const MobileNavLink = ({ onClick, icon, children, className = '' }: MobileNavLinkProps) => (
    <a href="#" onClick={(e) => { e.preventDefault(); onClick(); setIsMobileMenuOpen(false); }} className={`flex items-center space-x-3 px-3 py-2 text-base font-medium rounded-md ${className}`}>
      <Icon path={icon} />
      <span>{children}</span>
    </a>
  );

  const UploadModal = ({ isOpen, onClose }: { isOpen: boolean; onClose: () => void; }) => {
    const [title, setTitle] = useState('');
    const [description, setDescription] = useState('');
    const [tags, setTags] = useState('');
    const [imageFile, setImageFile] = useState<File | null>(null);
    const [error, setError] = useState('');

    const handleSubmit: FormEventHandler = async (e) => {
      e.preventDefault();
      setError('');
      if (!user) return;
      
      const enteredTags = tags.split(' ').filter(t => t);

      if (!title || !imageFile || !description) {
        setError('Please fill in all fields and select an image.');
        return;
      }

      const response = await API.createPostRequest(
        title, description,
        enteredTags, imageFile.name,
        imageFile.type, imageFile.size,
        user
      );
      const data = await response.json();
      if (!response.ok) {
        setError(data.detail || `Upload failed with status ${response.status}.`);
        return;
      }
      const uploadUrl = data.fileUrl;
      if (!uploadUrl) {
        setError('Upload URL not provided by server.');
        return;
      }
      
      const uploadResponse = await API.patchFileUploadUrl(uploadUrl, imageFile, user);
      if (!uploadResponse.ok) {
        setError(`Image upload failed with status ${uploadResponse.status}.`);
        return;
      }
      navigate(`/posts/${data.id}`);
      onClose();
    };

    return (
      <Modal isOpen={isOpen} onClose={onClose}>
        <h2 className="text-2xl font-bold mb-4">Upload a Post</h2>
        <form onSubmit={handleSubmit}>
          <div className="mb-4">
          <label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="post-title">Title</label>
          <input id="post-title" type="text" value={title} onChange={(e) => setTitle(e.target.value)} className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" placeholder="e.g., My Awesome Picture"/>
          </div>
          <div className="mb-4">
          <label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="post-description">Description</label>
          <textarea id="post-description" rows={3} value={description} onChange={(e) => setDescription(e.target.value)} className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" placeholder="A short description of your image..."/>
          </div>
          <div className="mb-4">
          <label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="post-tags">Tags (space-separated)</label>
          <input id="post-tags" type="text" value={tags} onChange={(e) => setTags(e.target.value)} className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" placeholder="e.g., high-res"/>
          </div>
          <div className="mb-6">
          <label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="post-image">Image</label>
          <input id="post-image" type="file" accept="image/*" onChange={(e) => {
            const files = e.target.files
            if (files && files.length > 0) setImageFile(files[0])
          }} className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:shadow-outline"/>
          </div>
          {error && <p className="text-red-500 text-xs italic mb-4">{error}</p>}
          <div className="flex items-center justify-end">
          <button type="submit" className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline disabled:bg-blue-300" disabled={!title || !imageFile || !description}>Upload</button>
          </div>
        </form>
      </Modal>
    );
  };

  const RegisterModal = ({ isOpen, onClose }: { isOpen: boolean; onClose: () => void; }) => {
    const [username, setUsername] = useState('');
    const [email, setEmail] = useState('');
    const [password, setPassword] = useState('');
    const [confirmPassword, setConfirmPassword] = useState('');
    const [error, setError] = useState('');

    const handleSubmit: FormEventHandler = async (e) => {
      e.preventDefault();
      setError('');
      if (password !== confirmPassword) {
        setError("Passwords do not match.");
        return;
      }
      
      const response = await API.register(username, email, password);
      if (!response.ok) {
        const data = await response.json();
        setError(data.detail || "Registration failed. Please try again.");
        return;
      }
      
      // Automatically log in the user after successful registration
      const loginResponse = await API.login(email, password);
      if (loginResponse.ok) {
        const loginData = await loginResponse.json();
        login(loginData.accessToken, loginData.refreshToken);
      }
      
      onClose();
      setUsername('');
      setEmail('');
      setPassword('');
      setConfirmPassword('');
    };

    return (
      <Modal isOpen={isOpen} onClose={onClose}>
        <h2 className="text-2xl font-bold mb-4">Register</h2>
        <form onSubmit={handleSubmit}>
          <div className="mb-4">
            <label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="register-username">Username</label>
            <input id="register-username" type="text" value={username} onChange={(e) => setUsername(e.target.value)} className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" placeholder="Enter username" required/>
          </div>
          <div className="mb-4">
            <label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="register-email">Email</label>
            <input id="register-email" type="email" value={email} onChange={(e) => setEmail(e.target.value)} className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" placeholder="Enter email" required/>
          </div>
          <div className="mb-4">
            <label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="register-password">Password</label>
            <input id="register-password" type="password" value={password} onChange={(e) => setPassword(e.target.value)} className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" placeholder="Enter password" required/>
          </div>
          <div className="mb-6">
            <label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="confirm-password">Confirm Password</label>
            <input id="confirm-password" type="password" value={confirmPassword} onChange={(e) => setConfirmPassword(e.target.value)} className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:shadow-outline" placeholder="Confirm password" required/>
          </div>
          {error && <p className="text-red-500 text-xs italic mb-4">{error}</p>}
          <div className="flex items-center justify-between">
            <button type="submit" className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline">Register</button>
          </div>
        </form>
      </Modal>
    );
  };

  const LoginModal = ({ isOpen, onClose }: { isOpen: boolean; onClose: () => void; }) => {
    const [username, setUsername] = useState('');
    const [password, setPassword] = useState('');
    const [error, setError] = useState('');

    const handleSubmit: FormEventHandler = async (e) => {
      e.preventDefault();
      const response = await API.login(username, password);
      if (!response.ok) {
        setError("Login failed. Please check your credentials.");
        return;
      }
      const data = await response.json();
      login(data.accessToken, data.refreshToken);
      onClose();
      setUsername('');
      setPassword('');
    };

    return (
      <Modal isOpen={isLoginModalOpen} onClose={onClose}>
        <h2 className="text-2xl font-bold mb-4">Login</h2>
        <form onSubmit={handleSubmit}>
          <div className="mb-4">
            <label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="username">Email</label>
            <input id="username" type="email" value={username} onChange={(e) => setUsername(e.target.value)} className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" placeholder="Enter email"/>
          </div>
          <div className="mb-6">
            <label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="password">Password</label>
            <input id="password" type="password" value={password} onChange={(e) => setPassword(e.target.value)} className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:shadow-outline" placeholder="Enter password"/>
          </div>
          {error && <p className="text-red-500 text-xs italic mb-4">{error}</p>}
          <div className="flex items-center justify-between">
            <button type="submit" className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline">Sign In</button>
            <a href="#" onClick={(e) => { e.preventDefault(); onClose(); onRegisterClick(); }} className="inline-block align-baseline font-bold text-sm text-blue-500 hover:text-blue-800">
              Create an Account
            </a>
          </div>
        </form>
      </Modal>
    );
  };

  return (
    <>
      <header className="bg-white shadow-md sticky top-0 z-10">
      <div className="container mx-auto px-4">
        <div className="flex items-center justify-between h-16">
          <div className="flex items-center">
            <h1 className="text-2xl font-bold text-gray-800 cursor-pointer" onClick={onBack}>ImgBoard</h1>
          </div>

          {/* Desktop Nav */}
          <div className="hidden md:flex items-center space-x-2">
            <NavButton onClick={onTagsClick} icon={ICONS.tags} className="text-gray-600 hover:bg-gray-100">Tags</NavButton>
            {isLoading ? (
              <div className="px-4 py-2 font-semibold">Loading...</div>
            ) : user ? (
              <>
                <NavButton onClick={onUploadClick} icon={ICONS.upload} className="text-gray-600 hover:bg-gray-100">Upload</NavButton>
                <NavButton onClick={onLogout} icon={ICONS.logout} className="text-gray-600 hover:bg-gray-100">Logout</NavButton>
              </>
            ) : (
              <>
                <NavButton onClick={onLoginClick} icon={ICONS.login} className="bg-green-500 text-white hover:bg-green-600">Login</NavButton>
                <NavButton onClick={onRegisterClick} icon={ICONS.register} className="bg-blue-500 text-white hover:bg-blue-600">Register</NavButton>
              </>
            )}
          </div>
                
          {/* Mobile Menu Button */}
          <div className="md:hidden">
            <button onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)} className="p-2 rounded-md text-gray-600 hover:text-gray-900 hover:bg-gray-100">
              <Icon path={isMobileMenuOpen ? ICONS.close : ICONS.menu} />
            </button>
          </div>
        </div>
      </div>
        
      {/* Mobile Menu */}
      {isMobileMenuOpen && (
        <div className="md:hidden absolute top-16 left-0 right-0 bg-white shadow-lg p-2 z-20">
          <div className="space-y-1">
            <MobileNavLink onClick={onTagsClick} icon={ICONS.tags} className="text-gray-600 hover:bg-gray-100">Tags</MobileNavLink>
            {isLoading ? (
              <div className="px-3 py-2">Loading...</div>
            ) : user ? (
              <>
                <MobileNavLink onClick={onUploadClick} icon={ICONS.upload} className="text-gray-700 hover:bg-gray-100">Upload Image</MobileNavLink>
                <MobileNavLink onClick={onLogout} icon={ICONS.logout} className="text-red-600 hover:bg-red-50">Logout</MobileNavLink>
              </>
            ) : (
              <>
                <MobileNavLink onClick={onLoginClick} icon={ICONS.login} className="text-green-600 hover:bg-green-50">Login</MobileNavLink>
                <MobileNavLink onClick={onRegisterClick} icon={ICONS.register} className="text-blue-600 hover:bg-blue-50">Register</MobileNavLink>
              </>
            )}
          </div>
        </div>
      )}
      </header>
      <LoginModal isOpen={isLoginModalOpen} onClose={() => setIsLoginModalOpen(false)}/>
      <RegisterModal isOpen={isRegisterModalOpen} onClose={() => setIsRegisterModalOpen(false)}/>
      <UploadModal isOpen={isUploadModalOpen} onClose={() => setIsUploadModalOpen(false)}/>
    </>
  );
}
