import React, {
  createContext,
  useContext,
  useState,
  useEffect,
  useRef,
} from "react";
import {
  BrowserRouter as Router,
  Routes,
  Route,
  Link,
  useNavigate,
} from "react-router-dom";
import { useForm } from "react-hook-form";
import { BlogViewer } from "./utils/BlogViewer";
import { RequireAdmin } from "./utils/RouteGuard";
import { AdminPage } from "./utils/AdminPage";
import Unauthorized from "./utils/UnauthorizedPage";
import {
  FaGithub,
  FaGitAlt,
  FaLinkedin,
  FaTwitter,
  FaSun,
  FaMoon,
} from "react-icons/fa";
import type { Blog } from "./utils/types";
import { countWords } from "./utils/countWords";

// Base API URL from env
const API_URL = import.meta.env.VITE_API_URL || "http://localhost:8000";

// Auth Context
interface AuthContextProps {
  isAuthenticated: boolean;
  login: (token: string, user_id: number) => void;
  logout: () => void;
}
const AuthContext = createContext<AuthContextProps>({
  isAuthenticated: false,
  login: () => {},
  logout: () => {},
});
export const useAuth = () => useContext(AuthContext);

const AuthProvider: React.FC<{ children: React.ReactNode }> = ({
  children,
}) => {
  const [isAuthenticated, setIsAuthenticated] = useState(false);
  const navigate = useNavigate();

  useEffect(() => {
    const token = localStorage.getItem("token");
    setIsAuthenticated(!!token);
  }, []);

  const login = (token: string, user_id: number) => {
    localStorage.setItem("token", token);
    localStorage.setItem("user_id", user_id.toString());
    setIsAuthenticated(true);
  };

  const logout = () => {
    localStorage.removeItem("token");
    setIsAuthenticated(false);
    navigate("/signin");
  };

  return (
    <AuthContext.Provider value={{ isAuthenticated, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
};

function BlogPage() {
  const { isAuthenticated } = useAuth();
  const navigate = useNavigate();
  const [blogs, setBlogs] = useState<Blog[]>([]);

  useEffect(() => {
    fetch(`${API_URL}/blogs`)
      .then((res) => res.json())
      .then((data: Blog[]) => setBlogs(data))
      .catch((err) => console.error(err));
  }, []);

  return (
    <div>
      <div className="flex justify-end mb-4">
        <button
          onClick={() =>
            isAuthenticated ? navigate("/create") : navigate("/signin")
          }
          className="px-4 py-2 bg-green-600 text-white rounded hover:bg-green-700"
        >
          Create
        </button>
      </div>
      <div className="space-y-4">
        {blogs.map((blog) => (
          <Link
            key={blog.id}
            to={`/blog/${blog.id}`}
            className="block p-4 border rounded hover:bg-gray-100 dark:hover:bg-gray-800"
          >
            <h3 className="text-xl font-semibold">{blog.title}</h3>
            <p className="text-sm text-gray-500">By {blog.author_id}</p>
          </Link>
        ))}
      </div>
    </div>
  );
}

// Page for creating a blog post
function CreateBlog() {
  const [fileName, setFileName] = useState<string>("");
  const [title, setTitle] = useState<string>("");
  const username = localStorage.getItem("user_id") || "";
  const [author, setAuthor] = useState<string>(username);
  const [description, setDescription] = useState<string>("");
  const [content, setContent] = useState<string>("");
  const navigate = useNavigate();

  const handleFile = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file) return;
    const reader = new FileReader();
    reader.onload = () => {
      const text = reader.result as string;
      setContent(text);
      setFileName(file.name);
      const baseName = file.name.replace(/\.[^.]+$/, "");
      setTitle(baseName);
      setAuthor(username);
    };
    reader.readAsText(file);
  };

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    // Stubbed API call
    try {
      const body = {
        title: title,
        author_id: localStorage.getItem("user_id"),
        description: description,
        body: content,
        created_at: new Date(Date.now()).toISOString(),
        updated_at: new Date(Date.now()).toISOString(),
        published_at: new Date(Date.now()).toISOString(),
        word_count: countWords(content),
        version: 1,
        read_time: 0,
        language: "US",
      };
      const res = await fetch(`${API_URL}/blogs`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(body),
      });
      alert(res);
      navigate("/blog");
    } catch (err: any) {
      alert(err.message);
    }
  };

  return (
    <div className="max-w-xl mx-auto py-10 space-y-6">
      <h2 className="text-2xl font-bold">Create Post</h2>
      <div className="flex space-x-4">
        <label className="px-4 py-2 bg-gray-200 dark:bg-gray-700 rounded cursor-pointer hover:bg-gray-300 dark:hover:bg-gray-600">
          Upload File
          <input
            type="file"
            accept=".txt,.md"
            onChange={handleFile}
            className="hidden"
          />
        </label>
      </div>
      {fileName && (
        <form onSubmit={handleSubmit} className="space-y-4">
          <div>
            <label htmlFor="title" className="block text-sm font-medium mb-1">
              Title
            </label>
            <input
              id="title"
              type="text"
              value={title}
              onChange={(e) => setTitle(e.target.value)}
              className="w-full border border-gray-300 dark:border-gray-600 rounded px-3 py-2"
            />
          </div>
          <div>
            <label htmlFor="author" className="block text-sm font-medium mb-1">
              Author
            </label>
            <input
              id="author"
              type="text"
              value={author}
              onChange={(e) => setAuthor(e.target.value)}
              className="w-full border border-gray-300 dark:border-gray-600 rounded px-3 py-2"
            />
          </div>
          <div>
            <label
              htmlFor="description"
              className="block text-sm font-medium mb-1"
            >
              Description
            </label>
            <input
              id="description"
              type="text"
              value={description}
              onChange={(e) => setDescription(e.target.value)}
              className="w-full border border-gray-300 dark:border-gray-600 rounded px-3 py-2"
            />
          </div>
          <div>
            <label htmlFor="content" className="block text-sm font-medium mb-1">
              Content
            </label>
            <textarea
              id="content"
              rows={10}
              value={content}
              onChange={(e) => setContent(e.target.value)}
              className="w-full border border-gray-300 dark:border-gray-600 rounded px-3 py-2 max-h-96 overflow-y-auto resize-none"
            />
          </div>
          <button
            type="submit"
            className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700"
          >
            Submit
          </button>
        </form>
      )}
    </div>
  );
}

function App() {
  // Initialize theme from localStorage or default to light
  const [darkMode, setDarkMode] = useState<boolean>(() => {
    return localStorage.getItem("theme") === "dark";
  });

  // Sync dark mode state with <html> class and localStorage
  useEffect(() => {
    if (darkMode) {
      document.documentElement.classList.add("dark");
      localStorage.setItem("theme", "dark");
    } else {
      document.documentElement.classList.remove("dark");
      localStorage.setItem("theme", "light");
    }
  }, [darkMode]);

  return (
    <Router>
      <AuthProvider>
        <div className="min-h-screen bg-gray-100 dark:bg-gray-900 text-gray-900 dark:text-gray-100 transition-colors duration-300">
          <AppBar
            darkMode={darkMode}
            toggleDarkMode={() => setDarkMode((prev) => !prev)}
          />
          <div className="p-4">
            <Routes>
              <Route path="/" element={<LandingPage />} />
              <Route path="/blog" element={<BlogPage />} />
              <Route path="/blog/:slug" element={<BlogViewer />} />
              <Route path="/about" element={<About />} />
              <Route path="/contact" element={<Contact />} />
              <Route
                path="/admin"
                element={
                  <RequireAdmin>
                    <AdminPage />
                  </RequireAdmin>
                }
              />
              <Route path="/unauthorized" element={<Unauthorized />} />
              <Route path="/register" element={<Register />} />
              <Route path="/signin" element={<SignIn />} />
              <Route path="/profile" element={<Profile />} />
              <Route path="/create" element={<CreateBlog />} />
            </Routes>
          </div>
        </div>
      </AuthProvider>
    </Router>
  );
}

function AppBar({
  darkMode,
  toggleDarkMode,
}: {
  darkMode: boolean;
  toggleDarkMode: () => void;
}) {
  const { isAuthenticated, logout } = useAuth();
  const [menuOpen, setMenuOpen] = useState(false);
  const menuRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const handleClickOutside = (event: MouseEvent) => {
      if (
        menuOpen &&
        menuRef.current &&
        !menuRef.current.contains(event.target as Node)
      ) {
        setMenuOpen(false);
      }
    };
    document.addEventListener("mousedown", handleClickOutside);
    return () => document.removeEventListener("mousedown", handleClickOutside);
  }, [menuOpen]);

  return (
    <nav className="bg-white dark:bg-gray-800 shadow p-4 flex items-center relative">
      <Link to="/" className="font-bold text-blue-600 dark:text-blue-400">
        Home
      </Link>
      <Link
        to="/blog"
        className="ml-4 text-gray-800 dark:text-gray-200 hover:text-blue-600 dark:hover:text-blue-400"
      >
        Blog
      </Link>
      <Link
        to="/about"
        className="ml-4 text-gray-800 dark:text-gray-200 hover:text-blue-600 dark:hover:text-blue-400"
      >
        About Me
      </Link>
      <Link
        to="/contact"
        className="ml-4 text-gray-800 dark:text-gray-200 hover:text-blue-600 dark:hover:text-blue-400"
      >
        Contact
      </Link>
      <div className="ml-auto flex items-center space-x-4">
        {!isAuthenticated ? (
          <>
            <Link
              to="/register"
              className="px-3 py-1 bg-blue-600 text-white rounded hover:bg-blue-700"
            >
              Register
            </Link>
            <Link
              to="/signin"
              className="px-3 py-1 bg-gray-200 dark:bg-gray-700 text-gray-800 dark:text-gray-200 rounded hover:bg-gray-300 dark:hover:bg-gray-600"
            >
              Sign In
            </Link>
          </>
        ) : (
          <div className="relative" ref={menuRef}>
            <button
              onClick={() => setMenuOpen(!menuOpen)}
              className="w-8 h-8 rounded-full bg-gray-200 dark:bg-gray-700 flex items-center justify-center"
            >
              <span className="text-gray-700 dark:text-gray-200">U</span>
            </button>
            {menuOpen && (
              <div className="absolute right-0 mt-2 w-32 bg-white dark:bg-gray-700 shadow rounded">
                <Link
                  to="/profile"
                  className="block px-4 py-2 text-gray-800 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-600"
                >
                  Profile
                </Link>
                <button
                  onClick={logout}
                  className="w-full text-left block px-4 py-2 text-gray-800 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-600"
                >
                  Sign Out
                </button>
              </div>
            )}
          </div>
        )}
        <button
          onClick={toggleDarkMode}
          className="text-xl p-1 bg-gray-200 dark:bg-gray-700 rounded-full"
        >
          {darkMode ? <FaMoon /> : <FaSun />}
        </button>
      </div>
    </nav>
  );
}

// Pages and forms
function LandingPage() {
  return (
    <div className="text-center py-10">
      <h1 className="text-4xl font-bold mb-4">Welcome to My Site</h1>
      <p className="text-lg text-gray-700 dark:text-gray-300">
        Explore my blog, learn about me, or get in touch.
      </p>
    </div>
  );
}

function About() {
  return (
    <div className="py-10">
      <div className="flex justify-center items-end space-x-4">
        <img
          src="/images/photo1.jpg"
          alt="Photo 1"
          className="w-24 h-24 rounded-full"
        />
        <img
          src="/images/photo2.jpg"
          alt="Photo 2"
          className="w-24 h-24 rounded-full transform translate-y-4"
        />
        <img
          src="/images/photo3.jpg"
          alt="Photo 3"
          className="w-24 h-24 rounded-full"
        />
      </div>
      <div className="text-center mt-8 px-4">
        <h2 className="text-3xl font-bold mb-4">About Me</h2>
        <p className="text-lg text-gray-700 dark:text-gray-300 max-w-2xl mx-auto">
          I am a software engineer at Whisker who designs and implements
          whatever is highest priority. I work with every team in the
          engineering organization to coordinate mission-critical projects
          across backend, mobile, and firmware. I’m comfortable in many tech
          stacks and learn new ones quickly—never afraid to jump in the deep end
          and adapt on the fly.
        </p>
      </div>
      <div className="mt-8 flex flex-col items-center space-y-2">
        <a
          href="https://github.com/amuszyn"
          className="flex items-center space-x-2 text-blue-600 hover:underline"
        >
          <FaGithub />
          <span>github.com/amuszyn</span>
        </a>
        <a
          href="https://gitea.muszyn.dev/"
          className="flex items-center space-x-2 text-blue-600 hover:underline"
        >
          <FaGitAlt />
          <span>gitea.muszyn.dev/</span>
        </a>
        <a
          href="https://www.linkedin.com/in/almuszynski/"
          className="flex items-center space-x-2 text-blue-600 hover:underline"
        >
          <FaLinkedin />
          <span>linkedin.com/in/almuszynski</span>
        </a>
        <a
          href="https://x.com/Muszynlol"
          className="flex items-center space-x-2 text-blue-600 hover:underline"
        >
          <FaTwitter />
          <span>x.com/Muszynlol</span>
        </a>
      </div>
    </div>
  );
}

function Contact() {
  return (
    <div className="text-center py-10">
      <h2 className="text-2xl font-bold mb-4">Contact</h2>
      <p>Contact page content coming soon.</p>
    </div>
  );
}

function Profile() {
  return (
    <div className="text-center py-10">
      <h2 className="text-2xl font-bold mb-4">Profile</h2>
      <p>Profile page coming soon.</p>
    </div>
  );
}

// Registration form with API integration
interface RegisterForm {
  username: string;
  email: string;
  password: string;
  confirmPassword: string;
}

function Register() {
  const navigate = useNavigate();
  const {
    register,
    handleSubmit,
    watch,
    formState: { errors },
  } = useForm<RegisterForm>();

  const onSubmit = async (data: RegisterForm) => {
    try {
      const response = await fetch(`${API_URL}/register`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          username: data.username,
          email: data.email,
          password: data.password,
        }),
      });
      if (!response.ok) {
        const err = await response.json();
        throw new Error(err.detail || "Registration failed");
      }
      navigate("/signin");
    } catch (err: any) {
      alert(err.message);
    }
  };

  return (
    <div className="max-w-md mx-auto py-10">
      <h2 className="text-2xl font-bold mb-6 text-center">Register</h2>
      <form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
        <div>
          <label htmlFor="username" className="block text-sm font-medium mb-1">
            Username
          </label>
          <input
            id="username"
            {...register("username", { required: true })}
            className="w-full border border-gray-300 dark:border-gray-600 rounded px-3 py-2"
          />
          {errors.username && (
            <span className="text-red-600 text-sm">Username is required</span>
          )}
        </div>

        <div>
          <label htmlFor="email" className="block text-sm font-medium mb-1">
            Email
          </label>
          <input
            id="email"
            type="email"
            {...register("email", {
              required: true,
              pattern: /^\S+@\S+\.\S+$/,
            })}
            className="w-full border border-gray-300 dark:border-gray-600 rounded px-3 py-2"
          />
          {errors.email && (
            <span className="text-red-600 text-sm">
              Valid email is required
            </span>
          )}
        </div>

        <div>
          <label htmlFor="password" className="block text-sm font-medium mb-1">
            Password
          </label>
          <input
            id="password"
            type="password"
            {...register("password", {
              required: true,
              pattern: /(?=.*[A-Z])(?=.*\d).+/,
            })}
            className="w-full border border-gray-300 dark:border-gray-600 rounded px-3 py-2"
          />
          {errors.password && (
            <span className="text-red-600 text-sm">
              Password must include uppercase and number
            </span>
          )}
        </div>

        <div>
          <label
            htmlFor="confirmPassword"
            className="block text-sm font-medium mb-1"
          >
            Confirm Password
          </label>
          <input
            id="confirmPassword"
            type="password"
            {...register("confirmPassword", {
              validate: (value) =>
                value === watch("password") || "Passwords do not match",
            })}
            className="w-full border border-gray-300 dark:border-gray-600 rounded px-3 py-2"
          />
          {errors.confirmPassword && (
            <span className="text-red-600 text-sm">
              {errors.confirmPassword.message}
            </span>
          )}
        </div>

        <button
          type="submit"
          className="w-full bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700"
        >
          Register
        </button>
      </form>
    </div>
  );
}

// Sign-in form with API integration
interface SignInForm {
  identifier: string;
  password: string;
}

function SignIn() {
  const navigate = useNavigate();
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<SignInForm>();
  const { login } = useAuth();

  const onSubmit = async (data: SignInForm) => {
    try {
      const body = new URLSearchParams();
      body.append("username", data.identifier);
      body.append("password", data.password);

      const response = await fetch(`${API_URL}/login`, {
        method: "POST",
        headers: { "Content-Type": "application/x-www-form-urlencoded" },
        body: body.toString(),
      });

      if (!response.ok) {
        const err = await response.json();
        throw new Error(err.detail || "Login failed");
      }

      const tokenData = await response.json();
      alert(response);
      login(tokenData.access_token, tokenData.user_id);
      navigate("/");
    } catch (err: any) {
      alert(err.message);
    }
  };

  return (
    <div className="max-w-md mx-auto py-10">
      <h2 className="text-2xl font-bold mb-6 text-center">Sign In</h2>
      <form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
        <div>
          <label
            htmlFor="identifier"
            className="block text-sm font-medium mb-1"
          >
            Username or Email
          </label>
          <input
            id="identifier"
            {...register("identifier", { required: true })}
            className="w-full border border-gray-300 dark:border-gray-600 rounded px-3 py-2"
          />
          {errors.identifier && (
            <span className="text-red-600 text-sm">This field is required</span>
          )}
        </div>

        <div>
          <label
            htmlFor="signinPassword"
            className="block text-sm font-medium mb-1"
          >
            Password
          </label>
          <input
            id="signinPassword"
            type="password"
            {...register("password", { required: true })}
            className="w-full border border-gray-300 dark:border-gray-600 rounded px-3 py-2"
          />
          {errors.password && (
            <span className="text-red-600 text-sm">Password is required</span>
          )}
        </div>

        <button
          type="submit"
          className="w-full bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700"
        >
          Sign In
        </button>
      </form>
    </div>
  );
}

export default App;
