import { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { api } from "../api/client";

interface MemberRead {
  id: string;
  display_name: string;
  email: string;
  avatar_url: string | null;
  nc_username: string | null;
  nc_url: string | null;
  nc_configured: boolean;
}

const getMe = () => api.get<MemberRead>("/auth/me");
const updateSettings = (data: {
  display_name?: string;
  nc_url?: string;
  nc_username?: string;
  nc_password?: string;
  avatar_url?: string;
}) => api.patch<MemberRead>("/auth/me/settings", data);

const inputStyle: React.CSSProperties = {
  width: "100%",
  padding: "8px 12px",
  background: "var(--bg-inset)",
  border: "1px solid var(--border)",
  borderRadius: 7,
  color: "var(--text)",
  fontSize: 14,
  boxSizing: "border-box",
};

function SettingsForm({ me, onBack }: { me: MemberRead; onBack: () => void }) {
  const qc = useQueryClient();
  const [displayName, setDisplayName] = useState(me.display_name ?? "");
  const [ncUrl, setNcUrl] = useState(me.nc_url ?? "");
  const [ncUsername, setNcUsername] = useState(me.nc_username ?? "");
  const [ncPassword, setNcPassword] = useState("");
  const [avatarUrl, setAvatarUrl] = useState(me.avatar_url ?? "");
  const [uploading, setUploading] = useState(false);
  const [saved, setSaved] = useState(false);
  const [error, setError] = useState<string | null>(null);

  // Keep local avatarUrl in sync when the server-side value changes (e.g. after
  // a background refetch or a change made on another device).
  useEffect(() => {
    setAvatarUrl(me.avatar_url ?? "");
  }, [me.avatar_url]);

  // Image resizing function
  const resizeImage = (file: File, maxWidth: number, maxHeight: number): Promise<File> => {
    return new Promise((resolve, reject) => {
      const img = new Image();
      const reader = new FileReader();
      
      reader.onload = (event) => {
        if (typeof event.target?.result !== 'string') {
          reject(new Error('Failed to read file'));
          return;
        }
        
        img.onload = () => {
          const canvas = document.createElement('canvas');
          let width = img.width;
          let height = img.height;
          
          // Calculate new dimensions
          if (width > height) {
            if (width > maxWidth) {
              height *= maxWidth / width;
              width = maxWidth;
            }
          } else {
            if (height > maxHeight) {
              width *= maxHeight / height;
              height = maxHeight;
            }
          }
          
          canvas.width = width;
          canvas.height = height;
          
          const ctx = canvas.getContext('2d');
          if (!ctx) {
            reject(new Error('Failed to get canvas context'));
            return;
          }
          
          ctx.drawImage(img, 0, 0, width, height);
          
          canvas.toBlob((blob) => {
            if (!blob) {
              reject(new Error('Failed to create blob'));
              return;
            }
            
            const resizedFile = new File([blob], file.name, {
              type: 'image/jpeg',
              lastModified: Date.now()
            });
            
            resolve(resizedFile);
          }, 'image/jpeg', 0.8); // JPEG quality 80%
        };
        
        img.onerror = reject;
        img.src = event.target?.result;
      };
      
      reader.onerror = reject;
      reader.readAsDataURL(file);
    });
  };

  const saveMutation = useMutation({
    mutationFn: () =>
      updateSettings({
        display_name: displayName || undefined,
        nc_url: ncUrl || undefined,
        nc_username: ncUsername || undefined,
        nc_password: ncPassword || undefined,
        avatar_url: avatarUrl || undefined,
      }),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["me"] });
      setSaved(true);
      setNcPassword("");
      setError(null);
      setTimeout(() => setSaved(false), 3000);
    },
    onError: (err) => setError(err instanceof Error ? err.message : "Save failed"),
  });

  const labelStyle: React.CSSProperties = {
    display: "block", color: "var(--text-muted)", fontSize: 11, marginBottom: 6,
  };

  return (
    <>
      <section style={{ marginBottom: 32 }}>
        <h2 style={{ fontSize: 11, fontWeight: 500, color: "var(--text-muted)", textTransform: "uppercase", letterSpacing: "0.7px", marginBottom: 16 }}>PROFILE</h2>
        <div style={{ display: "flex", alignItems: "center", gap: 16, marginBottom: 16 }}>
        {avatarUrl && (
          <img src={avatarUrl} alt="Profile" style={{ width: 64, height: 64, borderRadius: "50%", objectFit: "cover" }} />
        )}
        <div style={{ flex: 1 }}>
          <label style={labelStyle}>DISPLAY NAME</label>
          <input value={displayName} onChange={(e) => setDisplayName(e.target.value)} style={inputStyle} />
          <p style={{ color: "var(--text-subtle)", fontSize: 11, margin: "4px 0 0" }}>{me.email}</p>
        </div>
      </div>
      </section>

      <section style={{ marginBottom: 32 }}>
        <h2 style={{ fontSize: 11, fontWeight: 500, color: "var(--text-muted)", textTransform: "uppercase", letterSpacing: "0.7px", marginBottom: 8 }}>Nextcloud Connection</h2>
        <p style={{ color: "var(--text-subtle)", fontSize: 12, marginBottom: 16 }}>
          Configure your personal Nextcloud credentials. When set, all file operations (band folders, song uploads, scans) will use these credentials.
        </p>

        <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 16 }}>
          <span style={{ display: "inline-block", width: 8, height: 8, borderRadius: "50%", background: me.nc_configured ? "var(--teal)" : "var(--text-muted)" }} />
          <span style={{ fontSize: 12, color: me.nc_configured ? "var(--teal)" : "var(--text-muted)" }}>
            {me.nc_configured ? "Connected" : "Not configured"}
          </span>
        </div>

        <label style={labelStyle}>NEXTCLOUD URL</label>
        <input value={ncUrl} onChange={(e) => setNcUrl(e.target.value)} placeholder="https://cloud.example.com" style={inputStyle} />

        <label style={{ ...labelStyle, marginTop: 12 }}>USERNAME</label>
        <input value={ncUsername} onChange={(e) => setNcUsername(e.target.value)} style={inputStyle} />

        <label style={{ ...labelStyle, marginTop: 12 }}>PASSWORD / APP PASSWORD</label>
        <input
          type="password"
          value={ncPassword}
          onChange={(e) => setNcPassword(e.target.value)}
          placeholder={me.nc_configured ? "••••••••  (leave blank to keep existing)" : ""}
          style={inputStyle}
        />
        <p style={{ color: "var(--text-subtle)", fontSize: 11, margin: "4px 0 0" }}>
          Use an app password from Nextcloud Settings → Security for better security.
        </p>
      </section>

      <section style={{ marginBottom: 32 }}>
        <h2 style={{ fontSize: 11, fontWeight: 500, color: "var(--text-muted)", textTransform: "uppercase", letterSpacing: "0.7px", marginBottom: 16 }}>AVATAR</h2>
        <div style={{ display: "flex", gap: 12, alignItems: "center", marginBottom: 16 }}>
          <input
            type="file"
            accept="image/*"
            onChange={async (e) => {
              const file = e.target.files?.[0];
              if (file) {
                setUploading(true);

                try {
                  // Check file size and resize if needed
                  const maxSize = 4 * 1024 * 1024; // 4MB (more conservative to account for base64 overhead)
                  let processedFile = file;

                  if (file.size > maxSize) {
                    processedFile = await resizeImage(file, 800, 800); // Max 800x800
                  }

                  const formData = new FormData();
                  formData.append('file', processedFile, processedFile.name || file.name);

                  const response = await api.upload<MemberRead>('/auth/me/avatar', formData);

                  setAvatarUrl(response.avatar_url || '');
                  qc.invalidateQueries({ queryKey: ['me'] });
                  qc.invalidateQueries({ queryKey: ['comments'] });
                } catch (err) {
                  let errorMessage = 'Failed to upload avatar. Please try again.';

                  if (err instanceof Error) {
                    errorMessage = err.message;
                    if (err.message.includes('413')) {
                      errorMessage = 'File too large. Maximum size is 5MB. Please choose a smaller image.';
                    } else if (err.message.includes('422')) {
                      errorMessage = 'Invalid image file. Please upload a valid image (JPG, PNG, etc.).';
                    }
                  } else if (typeof err === 'object' && err !== null) {
                    const errorObj = err as { status?: number; data?: { detail?: string } };
                    if (errorObj.status === 422 && errorObj.data?.detail) {
                      errorMessage = errorObj.data.detail;
                    }
                  }
                  
                  setError(errorMessage);
                } finally {
                  setUploading(false);
                }
              }
            }}
            style={{ display: "none" }}
            id="avatar-upload"
          />
          <label htmlFor="avatar-upload" style={{
            background: "var(--accent)",
            border: "none",
            borderRadius: 6,
            color: "var(--accent-fg)",
            cursor: "pointer",
            padding: "8px 16px",
            fontWeight: 600,
            fontSize: 13,
          }}>
            {uploading ? "Uploading..." : "Upload Avatar"}
          </label>
          <button
            onClick={async () => {
              try {
                const seed = Math.random().toString(36).substring(2, 15);
                const newAvatarUrl = `https://api.dicebear.com/9.x/identicon/svg?seed=${seed}&backgroundType=gradientLinear&size=128`;
                await updateSettings({ avatar_url: newAvatarUrl });
                setAvatarUrl(newAvatarUrl);
                qc.invalidateQueries({ queryKey: ["me"] });
                qc.invalidateQueries({ queryKey: ["comments"] });
              } catch (err) {
                setError(err instanceof Error ? err.message : 'Failed to update avatar');
              }
            }}
            style={{
              background: "none",
              border: "1px solid var(--border)",
              borderRadius: 6,
              color: "var(--text)",
              cursor: "pointer",
              padding: "8px 16px",
              fontSize: 13,
            }}
          >
            Generate Random
          </button>
        </div>
        {avatarUrl && (
          <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
            <img 
              src={avatarUrl} 
              alt="Preview" 
              style={{ width: 48, height: 48, borderRadius: "50%", objectFit: "cover" }}
              onError={() => {
                setAvatarUrl(`https://api.dicebear.com/9.x/identicon/svg?seed=${me.id}&backgroundType=gradientLinear&size=128`);
              }}
            />
            <button
              onClick={async () => {
                try {
                  await updateSettings({ avatar_url: "" });
                  setAvatarUrl("");
                  qc.invalidateQueries({ queryKey: ["me"] });
                  qc.invalidateQueries({ queryKey: ["comments"] });
                } catch (err) {
                  setError(err instanceof Error ? err.message : 'Failed to remove avatar');
                }
              }}
              style={{ 
                background: "none", 
                border: "none", 
                color: "var(--danger)", 
                cursor: "pointer", 
                fontSize: 12 
              }}
            >
              Remove
            </button>
          </div>
        )}
      </section>

      {error && <p style={{ color: "var(--danger)", fontSize: 13, marginBottom: 12 }}>{error}</p>}
      {saved && <p style={{ color: "var(--teal)", fontSize: 13, marginBottom: 12 }}>Settings saved.</p>}

      <div style={{ display: "flex", gap: 8 }}>
        <button
          onClick={() => saveMutation.mutate()}
          disabled={saveMutation.isPending}
          style={{ background: "var(--accent)", border: "none", borderRadius: 6, color: "var(--accent-fg)", cursor: "pointer", padding: "10px 24px", fontWeight: 600, fontSize: 14 }}
        >
          {saveMutation.isPending ? "Saving…" : "Save Settings"}
        </button>
        <button
          onClick={onBack}
          style={{ background: "none", border: "1px solid var(--border)", borderRadius: 6, color: "var(--text-muted)", cursor: "pointer", padding: "10px 18px", fontSize: 14 }}
        >
          Cancel
        </button>
      </div>
    </>
  );
}

export function SettingsPage() {
  const navigate = useNavigate();
  const { data: me, isLoading } = useQuery({ queryKey: ["me"], queryFn: getMe });

  return (
    <div style={{ padding: 24 }}>
      <div style={{ maxWidth: 540, margin: "0 auto" }}>
        <h1 style={{ color: "var(--text)", margin: "0 0 24px", fontSize: 17, fontWeight: 500 }}>
          Settings
        </h1>

        {isLoading && <p style={{ color: "var(--text-muted)" }}>Loading...</p>}
        {me && <SettingsForm me={me} onBack={() => navigate(-1)} />}
      </div>
    </div>
  );
}
