import React, { useState } from "react";
import { createPlayer } from "../api";
import { User } from "../../components/interfaces/users";

type UserRow = { [key: string]: string };

function parseCSV(text: string): UserRow[] {
    // Basic CSV parser supporting quoted fields and commas inside quotes.
    // Returns array of objects using the first row as header.
    const rows: string[][] = [];
    const regex = /(?:"([^"]*(?:""[^"]*)*)"|([^",\r\n]*))(,|\r?\n|$)/g;

    let row: string[] = [];
    let match: RegExpExecArray | null;
    let i = 0;
    while ((match = regex.exec(text)) !== null) {
        const quoted = match[1];
        const plain = match[2];
        const delim = match[3];

        const value = quoted !== undefined
            ? quoted.replace(/""/g, '"')
            : (plain ?? "");
        row.push(value);

        if (delim === "\n" || delim === "\r\n" || delim === "") {
            rows.push(row);
            row = [];
        }

        // safety guard to avoid infinite loops
        if (++i > 10_000_000) break;
    }

    if (rows.length === 0) return [];

    const header = rows[0].map(h => h.trim());
    const dataRows = rows.slice(1).filter(r => r.length > 1 || (r.length === 1 && r[0] !== ""));

    return dataRows.map(r => {
        const obj: UserRow = {};
        for (let j = 0; j < header.length; j++) {
            obj[header[j] ?? `col${j}`] = (r[j] ?? "").trim();
        }
        return obj;
    });
}

async function postUsersBatch(endpoint: string, users: UserRow[]) {
    // const res = await fetch(endpoint, {
    //     method: "POST",
    //     headers: { "Content-Type": "application/json" },
    //     body: JSON.stringify({ users }),
    // });

    // if (!res.ok) {
    //     const text = await res.text();
    //     throw new Error(`API error ${res.status}: ${text}`);
    // }
    // return res.json();
    const normalize = (s: string) => s.toLowerCase().replace(/[^a-z0-9]/g, "");
    const find = (row: UserRow, candidates: string[]) => {
        const candNorm = candidates.map(c => normalize(c));
        for (const k of Object.keys(row)) {
            if (candNorm.includes(normalize(k))) return (row[k] ?? "").trim();
        }
        return undefined;
    };

    const mapped: User[] = users.map(r => {
        const uui = find(r, ["uuid", "id", "userId"]) || "";
        const Username = find(r, ["username", "user_name", "user"]) || "";
        const Email = find(r, ["email", "e-mail"]) || "";
        const firstName = find(r, ["firstName", "first_name", "firstname", "first name"]) || "";
        const lastName = find(r, ["lastName", "last_name", "lastname", "last name"]) || "";
        const phone = find(r, ["phone", "phoneNumber", "phonenumber", "mobile"]) || undefined;
        const position = find(r, ["position", "role"]) || undefined;
        const jerseyNumber = find(r, ["jersey", "number", "jerseyNumber"]) || undefined;
        const team = find(r, ["team", "club"]) || undefined;
        const dob = find(r, ["dob", "dateOfBirth", "date_of_birth", "birthdate"]) || undefined;

        // Adjust the returned shape to match your actual User interface.
        return {
            uui,
            Username,
            Email,
            firstName,
            lastName,
            phone,
            position,
            jerseyNumber,
            team,
            dob,
        } as unknown as User;
    });

    mapped.forEach((u, idx) => {
    console.log("Creating user:", idx, u);
    createPlayer({
                    Username: u.Username,
                    Email: u.Email,
                },
                localStorage.getItem("token") || "");
    });
    // return await createPlayer(mapped, localStorage.getItem("token") || "");
    
}

export default function TMP() {
    const [preview, setPreview] = useState<UserRow[] | null>(null);
    const [fileName, setFileName] = useState<string | null>(null);
    const [status, setStatus] = useState<string | null>(null);
    const [errors, setErrors] = useState<string[] | null>(null);
    const [isUploading, setIsUploading] = useState(false);

    const onFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        setStatus(null);
        setErrors(null);
        const file = e.target.files?.[0];
        if (!file) return;
        setFileName(file.name);
        const reader = new FileReader();
        reader.onload = () => {
            const text = String(reader.result ?? "");
            try {
                const parsed = parseCSV(text);
                setPreview(parsed.slice(0, 50)); // preview first 50 rows
            } catch (err) {
                setErrors([String(err)]);
                setPreview(null);
            }
        };
        reader.onerror = () => {
            setErrors(["Failed to read file"]);
            setPreview(null);
        };
        reader.readAsText(file, "utf-8");
    };

    const validateUsers = (users: UserRow[]) => {
        const problems: string[] = [];
        // require "email" column (case-insensitive)
        const sample = users[0] ?? {};
        const hasEmailHeader = Object.keys(sample).some(k => k.toLowerCase() === "email");
        if (!hasEmailHeader) problems.push('CSV must contain an "email" column.');
        // quick email validation for each row
        const emailKey = hasEmailHeader ? Object.keys(sample).find(k => k.toLowerCase() === "email")! : null;
        if (emailKey) {
            users.forEach((u, idx) => {
                const val = (u[emailKey] ?? "").trim();
                if (!val) problems.push(`Row ${idx + 2}: missing email`);
                else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val)) problems.push(`Row ${idx + 2}: invalid email "${val}"`);
            });
        }
        return { problems, emailKey };
    };

    const onUpload = async () => {
        setStatus(null);
        setErrors(null);
        if (!preview) {
            setErrors(["No parsed data to upload. Choose a CSV file first."]);
            return;
        }

        // In a real flow you should re-parse the file to get all rows (we only stored preview).
        // For simplicity here we assume preview contains the whole parsed dataset when small.
        // If you expect large files, store entire parsed array in state instead of preview.
        // For this example, we will assume preview contains all rows (adjust as needed).
        const users = preview;

        const { problems, emailKey } = validateUsers(users);
        if (problems.length) {
            setErrors(problems);
            return;
        }

        setIsUploading(true);
        setStatus("Uploading...");
        try {
            // Adjust endpoint to match your backend API
            const endpoint = "/api/users/bulk";
            // send in chunks to avoid huge payloads
            const chunkSize = 100;
            for (let i = 0; i < users.length; i += chunkSize) {
                const chunk = users.slice(i, i + chunkSize).map(u => {
                    // optional: rename fields to backend expected shape
                    // e.g. map "firstName" -> "first_name" etc.
                    return u;
                });
                await postUsersBatch(endpoint, chunk);
            }
            setStatus(`Uploaded ${users.length} users successfully.`);
        } catch (err: any) {
            setErrors([err.message ?? String(err)]);
            setStatus("Upload failed.");
        } finally {
            setIsUploading(false);
        }
    };

    return (
        <div style={{ padding: 16 }}>
            <h2>Upload users CSV</h2>

            <input type="file" accept=".csv,text/csv" onChange={onFileChange} />
            {fileName && <div>Selected file: {fileName}</div>}

            {preview && (
                <>
                    <h4>Preview (first {preview.length} rows)</h4>
                    <div style={{ maxHeight: 300, overflow: "auto", border: "1px solid #ddd", padding: 8 }}>
                        <table style={{ width: "100%", borderCollapse: "collapse" }}>
                            <thead>
                                <tr>
                                    {Object.keys(preview[0]).map(k => (
                                        <th key={k} style={{ borderBottom: "1px solid #ccc", textAlign: "left", padding: 4 }}>{k}</th>
                                    ))}
                                </tr>
                            </thead>
                            <tbody>
                                {preview.map((row, ri) => (
                                    <tr key={ri}>
                                        {Object.keys(preview[0]).map((k, ci) => (
                                            <td key={ci} style={{ padding: 4, borderBottom: "1px solid #f3f3f3" }}>{row[k]}</td>
                                        ))}
                                    </tr>
                                ))}
                            </tbody>
                        </table>
                    </div>
                </>
            )}

            <div style={{ marginTop: 12 }}>
                <button onClick={onUpload} disabled={isUploading || !preview}>
                    {isUploading ? "Uploading..." : "Upload to API"}
                </button>
            </div>

            {status && <div style={{ marginTop: 8 }}>{status}</div>}
            {errors && (
                <div style={{ marginTop: 8, color: "crimson" }}>
                    <strong>Errors:</strong>
                    <ul>
                        {errors.map((e, i) => <li key={i}>{e}</li>)}
                    </ul>
                </div>
            )}
        </div>
    );
}