import { createContext, useContext, useEffect, useState, type ReactNode } from "react";

export type Lang = "en" | "bn";

// English → Bangla phrasebook. Matches whole trimmed text-node values and
// common attribute values (placeholder/title/aria-label) anywhere in the DOM.
const EN_BN: Record<string, string> = {
  // Nav / chrome
  "Dashboard": "ড্যাশবোর্ড",
  "Guards": "গার্ডস",
  "Rosters": "রোস্টার",
  "Attendance": "উপস্থিতি",
  "Duty Posts": "ডিউটি পোস্ট",
  "Duty Post": "ডিউটি পোস্ট",
  "QR Codes": "কিউআর কোড",
  "Leaves": "ছুটি",
  "Reports": "রিপোর্ট",
  "Salary": "বেতন",
  "Sign out": "সাইন আউট",
  "Sign in": "সাইন ইন",
  "Sign up": "সাইন আপ",
  "Loading…": "লোড হচ্ছে…",
  "GuardForce Pro": "গার্ডফোর্স প্রো",

  // Common actions
  "Save": "সংরক্ষণ",
  "Cancel": "বাতিল",
  "Delete": "মুছুন",
  "Edit": "সম্পাদনা",
  "Add": "যোগ করুন",
  "Search": "অনুসন্ধান",
  "Print": "প্রিন্ট",
  "Submit": "জমা দিন",
  "Confirm": "নিশ্চিত করুন",
  "Create": "তৈরি করুন",
  "Update": "আপডেট",
  "Close": "বন্ধ",
  "Back": "ফিরে যান",
  "Next": "পরবর্তী",
  "Previous": "পূর্ববর্তী",
  "View": "দেখুন",
  "Approve": "অনুমোদন",
  "Reject": "প্রত্যাখ্যান",
  "Refresh": "রিফ্রেশ",
  "Export": "এক্সপোর্ট",
  "Download": "ডাউনলোড",
  "Upload": "আপলোড",
  "Filter": "ফিল্টার",
  "Reset": "রিসেট",
  "Today": "আজ",
  "Date": "তারিখ",
  "Time": "সময়",
  "Status": "অবস্থা",
  "Type": "ধরন",
  "Name": "নাম",
  "Full Name": "পুরো নাম",
  "Full name": "পুরো নাম",
  "Phone": "ফোন",
  "Email": "ইমেইল",
  "Password": "পাসওয়ার্ড",
  "Address": "ঠিকানা",
  "Notes": "নোট",
  "Message": "বার্তা",
  "Reason": "কারণ",
  "Actions": "কর্ম",
  "Total": "মোট",
  "Total: ": "মোট: ",
  "Active": "সক্রিয়",
  "Inactive": "নিষ্ক্রিয়",
  "Inactive / Other": "নিষ্ক্রিয় / অন্যান্য",
  "Suspended": "স্থগিত",
  "Terminated": "অপসারিত",
  "Other": "অন্যান্য",
  "Pending": "অপেক্ষমান",
  "Approved": "অনুমোদিত",
  "Rejected": "প্রত্যাখ্যাত",
  "Cancelled": "বাতিল",
  "Completed": "সম্পন্ন",
  "Scheduled": "নির্ধারিত",
  "Flagged": "চিহ্নিত",
  "Present": "উপস্থিত",
  "Absent": "অনুপস্থিত",
  "Checked in": "চেক-ইন হয়েছে",
  "Checked out": "চেক-আউট হয়েছে",
  "Check-in": "চেক-ইন",
  "Check-out": "চেক-আউট",
  "New Check-in": "নতুন চেক-ইন",
  "Check-in date": "চেক-ইন তারিখ",

  // Auth / landing
  "Welcome": "স্বাগতম",
  "Sign in or create an account to continue": "চালিয়ে যেতে সাইন ইন করুন বা অ্যাকাউন্ট তৈরি করুন",
  "Create account": "অ্যাকাউন্ট তৈরি করুন",
  "Guard Sign In": "গার্ড সাইন ইন",
  "Guard Portal": "গার্ড পোর্টাল",
  "Employee ID": "এমপ্লয়ী আইডি",
  "ID No": "আইডি নম্বর",
  "Guard ID": "গার্ড আইডি",
  "Page not found": "পেজ পাওয়া যায়নি",

  // Guards
  "Add New Guard": "নতুন গার্ড যোগ করুন",
  "Edit Guard": "গার্ড সম্পাদনা",
  "Security Guards": "সিকিউরিটি গার্ড",
  "Manage your guard roster": "আপনার গার্ড রোস্টার পরিচালনা করুন",
  "Total Guards": "মোট গার্ড",
  "Guard": "গার্ড",
  "Guard not found.": "গার্ড পাওয়া যায়নি।",
  "No guards found.": "কোন গার্ড পাওয়া যায়নি।",
  "No guards match your filters.": "আপনার ফিল্টারের সাথে কোন গার্ড মেলে না।",
  "No guards found for this salary sheet.": "এই বেতন শীটের জন্য কোন গার্ড পাওয়া যায়নি।",
  "Delete guard?": "গার্ড মুছবেন?",

  // Duty posts
  "All Duty Posts": "সকল ডিউটি পোস্ট",
  "All posts": "সকল পোস্ট",
  "Add a post / location": "একটি পোস্ট / অবস্থান যোগ করুন",
  "Post name": "পোস্টের নাম",
  "Post": "পোস্ট",
  "Post / Location QR": "পোস্ট / অবস্থান কিউআর",
  "No duty posts yet.": "এখনো কোন ডিউটি পোস্ট নেই।",
  "Delete duty post?": "ডিউটি পোস্ট মুছবেন?",
  "Contact": "যোগাযোগ",
  "Contact person": "যোগাযোগকারী ব্যক্তি",
  "Contact phone": "যোগাযোগ ফোন",
  "Geofence": "জিওফেন্স",
  "Latitude": "অক্ষাংশ",
  "Longitude": "দ্রাঘিমাংশ",
  "Location": "অবস্থান",
  "Coords": "স্থানাঙ্ক",
  "Client": "ক্লায়েন্ট",

  // Rosters / shifts
  "Duty Rosters": "ডিউটি রোস্টার",
  "Shift": "শিফট",
  "Shift A": "শিফট এ",
  "Shift B": "শিফট বি",
  "Shift C": "শিফট সি",
  "All shifts": "সকল শিফট",
  "Auto-shift": "অটো-শিফট",
  "Remove shift?": "শিফট সরাবেন?",
  "This shift will be deleted.": "এই শিফটটি মুছে ফেলা হবে।",
  "No roster entries.": "কোন রোস্টার এন্ট্রি নেই।",
  "Start": "শুরু",
  "End": "শেষ",
  "Start date": "শুরুর তারিখ",
  "End date": "শেষের তারিখ",
  "From": "থেকে",
  "Days": "দিন",
  "Duty": "ডিউটি",
  "Duty Hrs": "ডিউটি ঘন্টা",
  "Worked": "কাজ করেছে",
  "Logged": "লগ করা",

  // Attendance
  "Recent Attendance": "সাম্প্রতিক উপস্থিতি",
  "Live check-ins and check-outs": "লাইভ চেক-ইন এবং চেক-আউট",
  "Live check-ins for selected date range": "নির্বাচিত তারিখ পরিসরের জন্য লাইভ চেক-ইন",
  "No attendance records.": "কোন উপস্থিতি রেকর্ড নেই।",
  "No matching check-ins.": "কোন মিল খুঁজে পাওয়া যায়নি।",
  "Method": "পদ্ধতি",
  "Verification": "যাচাইকরণ",
  "Verify guard presence with QR or GPS": "কিউআর বা জিপিএস দিয়ে গার্ডের উপস্থিতি যাচাই করুন",
  "Scan post QR code": "পোস্ট কিউআর কোড স্ক্যান করুন",
  "Guard QR": "গার্ড কিউআর",
  "No post QR codes yet.": "এখনো কোন পোস্ট কিউআর কোড নেই।",
  "Local time": "স্থানীয় সময়",
  "Asia/Dhaka": "এশিয়া/ঢাকা",

  // Leaves
  "Leave requests": "ছুটির আবেদন",
  "Leave type": "ছুটির ধরন",
  "New leave request": "নতুন ছুটির আবেদন",
  "Submit a leave request for a guard.": "একজন গার্ডের জন্য ছুটির আবেদন জমা দিন।",
  "All submitted requests": "সকল জমা দেওয়া আবেদন",
  "All statuses": "সকল অবস্থা",
  "No leave requests.": "কোন ছুটির আবেদন নেই।",
  "Annual": "বার্ষিক",
  "Casual": "নৈমিত্তিক",
  "Sick": "অসুস্থতা",
  "Unpaid": "অবৈতনিক",
  "Custom": "কাস্টম",

  // Salary
  "Basic": "মূল",
  "Earned": "অর্জিত",
  "Deduction": "কর্তন",
  "Net": "নীট",
  "Rating": "রেটিং",

  // Reports / dashboard
  "Recent Activity": "সাম্প্রতিক কার্যক্রম",
  "No activity yet.": "এখনো কোন কার্যক্রম নেই।",
  "No records": "কোন রেকর্ড নেই",
  "Operations": "অপারেশনস",
  "Operations Report": "অপারেশন রিপোর্ট",

  // Print
  "Portrait": "পোর্ট্রেট",
  "Landscape": "ল্যান্ডস্কেপ",
  "Orient.": "ওরিয়েন্টেশন",
  "Size": "সাইজ",
  "Margin mm": "মার্জিন মিমি",

  // Misc
  "Joined": "যোগদান",
  "Shared with your team. Payload format: ": "আপনার দলের সাথে শেয়ার করা হয়েছে। পেলোড ফরম্যাট: ",
  "View all ": "সব দেখুন ",
};

// Attribute values (placeholders, aria-labels, titles)
const ATTR_EN_BN: Record<string, string> = {
  "All posts": "সকল পোস্ট",
  "All statuses": "সকল অবস্থা",
  "Assign duty post": "ডিউটি পোস্ট বরাদ্দ করুন",
  "Building / floor / details": "ভবন / তলা / বিস্তারিত",
  "How many guards do you manage?": "আপনি কতজন গার্ড পরিচালনা করেন?",
  "Name or ID": "নাম বা আইডি",
  "Optional reason": "ঐচ্ছিক কারণ",
  "Search by employee ID or name…": "এমপ্লয়ী আইডি বা নাম দিয়ে খুঁজুন…",
  "Search by name, ID, phone, email…": "নাম, আইডি, ফোন, ইমেইল দিয়ে খুঁজুন…",
  "Search by name, client, address…": "নাম, ক্লায়েন্ট, ঠিকানা দিয়ে খুঁজুন…",
  "Search guard or employee ID": "গার্ড বা এমপ্লয়ী আইডি খুঁজুন",
  "Search guard, ID or location": "গার্ড, আইডি বা অবস্থান খুঁজুন",
  "Search guard, post, location…": "গার্ড, পোস্ট, অবস্থান খুঁজুন…",
  "Select duty post": "ডিউটি পোস্ট নির্বাচন করুন",
  "Select guard": "গার্ড নির্বাচন করুন",
  "Site / Post": "সাইট / পোস্ট",
  "Your name": "আপনার নাম",
  "Toggle language": "ভাষা পরিবর্তন",
  "Toggle theme": "থিম পরিবর্তন",
  "Open menu": "মেনু খুলুন",
};

function buildReverse(d: Record<string, string>): Record<string, string> {
  const r: Record<string, string> = {};
  for (const [k, v] of Object.entries(d)) r[v] = k;
  return r;
}
const BN_EN = buildReverse(EN_BN);
const ATTR_BN_EN = buildReverse(ATTR_EN_BN);

const ATTRS = ["placeholder", "title", "aria-label"];

function translateText(value: string, lang: Lang, fwd: Record<string, string>, rev: Record<string, string>): string | null {
  const trimmed = value.trim();
  if (!trimmed) return null;
  const lead = value.match(/^\s*/)![0];
  const tail = value.match(/\s*$/)![0];
  const target = lang === "bn" ? fwd[trimmed] : rev[trimmed];
  if (target == null) return null;
  return lead + target + tail;
}

function translateNode(root: Node, lang: Lang) {
  // Text nodes
  const walker = document.createTreeWalker(root.nodeType === 1 ? (root as Element) : document.body, NodeFilter.SHOW_TEXT, {
    acceptNode(node) {
      const p = node.parentElement;
      if (!p) return NodeFilter.FILTER_REJECT;
      if (p.closest("script,style,noscript,code,pre,textarea")) return NodeFilter.FILTER_REJECT;
      return NodeFilter.FILTER_ACCEPT;
    },
  });
  let n: Node | null = walker.nextNode();
  while (n) {
    const next = translateText(n.nodeValue || "", lang, EN_BN, BN_EN);
    if (next != null) n.nodeValue = next;
    n = walker.nextNode();
  }
  // Attributes on element + descendants
  if (root.nodeType === 1) {
    const el = root as Element;
    const all = [el, ...Array.from(el.querySelectorAll("*"))];
    for (const e of all) {
      for (const a of ATTRS) {
        const v = e.getAttribute(a);
        if (!v) continue;
        const nv = translateText(v, lang, ATTR_EN_BN, ATTR_BN_EN);
        if (nv != null && nv !== v) e.setAttribute(a, nv);
      }
    }
  }
}

function translateWholeDocument(lang: Lang) {
  translateNode(document.body, lang);
}

type Ctx = { lang: Lang; setLang: (l: Lang) => void; toggle: () => void; t: (en: string) => string };
const I18nContext = createContext<Ctx | null>(null);

export function I18nProvider({ children }: { children: ReactNode }) {
  const [lang, setLangState] = useState<Lang>("en");

  // Initial language load
  useEffect(() => {
    const stored = (typeof window !== "undefined" && localStorage.getItem("lang")) as Lang | null;
    const initial: Lang = stored === "en" || stored === "bn" ? stored : "en";
    setLangState(initial);
    document.documentElement.lang = initial;
    if (initial === "bn") {
      // defer to after first paint of children
      queueMicrotask(() => translateWholeDocument("bn"));
    }
  }, []);

  // Re-translate whenever lang changes or DOM mutates
  useEffect(() => {
    translateWholeDocument(lang);
    const obs = new MutationObserver((mutations) => {
      for (const m of mutations) {
        if (m.type === "childList") {
          m.addedNodes.forEach((node) => {
            if (node.nodeType === 1 || node.nodeType === 3) translateNode(node, lang);
          });
        } else if (m.type === "characterData" && m.target.nodeValue) {
          const next = translateText(m.target.nodeValue, lang, EN_BN, BN_EN);
          if (next != null) m.target.nodeValue = next;
        } else if (m.type === "attributes" && m.target.nodeType === 1) {
          const el = m.target as Element;
          const a = m.attributeName!;
          if (!ATTRS.includes(a)) continue;
          const v = el.getAttribute(a);
          if (!v) continue;
          const nv = translateText(v, lang, ATTR_EN_BN, ATTR_BN_EN);
          if (nv != null && nv !== v) el.setAttribute(a, nv);
        }
      }
    });
    obs.observe(document.body, {
      subtree: true,
      childList: true,
      characterData: true,
      attributes: true,
      attributeFilter: ATTRS,
    });
    return () => obs.disconnect();
  }, [lang]);

  const setLang = (l: Lang) => {
    setLangState(l);
    localStorage.setItem("lang", l);
    document.documentElement.lang = l;
  };
  const toggle = () => setLang(lang === "en" ? "bn" : "en");
  const t = (en: string) => (lang === "bn" ? EN_BN[en] ?? en : en);

  return <I18nContext.Provider value={{ lang, setLang, toggle, t }}>{children}</I18nContext.Provider>;
}

export function useI18n() {
  const ctx = useContext(I18nContext);
  if (!ctx) throw new Error("useI18n must be used within I18nProvider");
  return ctx;
}