#!/usr/bin/env python3
"""
UDISE+ Student Data Manager
Automated tool for downloading, updating, and managing student data from UDISE+ portal

Author: Hermes Agent for Piyush (Senior Clerk, Government Highschool)
"""

import os
import time
import pandas as pd
from datetime import datetime
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from webdriver_manager.chrome import ChromeDriverManager
from selenium.common.exceptions import TimeoutException, NoSuchElementException
import json
import getpass

# ─── Configuration ────────────────────────────────────────────────────────────
CONFIG_FILE = os.path.expanduser("~/.udiseplus_config.json")
DEFAULT_DOWNLOAD_DIR = os.path.expanduser("~/UDISE_Data")
EXCEL_TEMPLATE = os.path.expanduser("~/UDISE_Data/student_master_template.xlsx")

# ─── Helper Functions ─────────────────────────────────────────────────────────

def load_config():
    """Load saved credentials and settings"""
    if os.path.exists(CONFIG_FILE):
        with open(CONFIG_FILE, 'r') as f:
            return json.load(f)
    return {}

def save_config(username, school_code, save_creds=False):
    """Save configuration"""
    config = {
        "username": username,
        "school_code": school_code,
        "last_login": datetime.now().isoformat()
    }
    if save_creds:
        # Note: In production, use keyring or encrypted storage
        config["saved_credentials"] = True
    with open(CONFIG_FILE, 'w') as f:
        json.dump(config, f, indent=2)

def ensure_directory(path):
    """Create directory if not exists"""
    os.makedirs(path, exist_ok=True)

def wait_for_element(driver, by, value, timeout=20):
    """Wait for element to be present"""
    try:
        return WebDriverWait(driver, timeout).until(
            EC.presence_of_element_located((by, value))
        )
    except TimeoutException:
        print(f"⚠️  Timeout waiting for element: {value}")
        return None

def wait_for_clickable(driver, by, value, timeout=20):
    """Wait for element to be clickable"""
    try:
        return WebDriverWait(driver, timeout).until(
            EC.element_to_be_clickable((by, value))
        )
    except TimeoutException:
        print(f"⚠️  Element not clickable: {value}")
        return None

# ─── Main Automation Class ─────────────────────────────────────────────────────

class UDISEPlusManager:
    """Main class for UDISE+ automation"""

    BASE_URL = "https://udiseplus.gov.in/"
    LOGIN_URL = "https://udiseplus.gov.in/login"

    def __init__(self, headless=False):
        """Initialize the manager"""
        self.driver = None
        self.headless = headless
        self.logged_in = False
        self.school_name = None
        self.school_code = None

    def setup_driver(self):
        """Setup Chrome driver"""
        print("🔧 Setting up Chrome driver...")
        options = Options()
        if self.headless:
            options.add_argument('--headless')

        # Download directory setup
        prefs = {
            "download.default_directory": DEFAULT_DOWNLOAD_DIR,
            "download.prompt_for_download": False,
            "download.directory_upgrade": True,
            "safebrowsing.enabled": True
        }
        options.add_experimental_option("prefs", prefs)

        # Other options
        options.add_argument('--disable-blink-features=AutomationControlled')
        options.add_experimental_option("excludeSwitches", ["enable-automation"])
        options.add_argument('--no-sandbox')
        options.add_argument('--disable-dev-shm-usage')

        service = Service(ChromeDriverManager().install())
        self.driver = webdriver.Chrome(service=service, options=options)
        self.driver.maximize_window()
        print("✓ Chrome driver ready")

    def login(self, username, password, school_code):
        """Login to UDISE+ portal"""
        print(f"🔐 Logging in as {username}...")
        self.school_code = school_code

        try:
            self.driver.get(self.LOGIN_URL)
            time.sleep(3)

            # Enter username
            user_field = wait_for_element(self.driver, By.NAME, "username")
            if not user_field:
                # Try alternative selectors
                user_field = wait_for_element(self.driver, By.ID, "username")
            user_field.send_keys(username)

            # Enter password
            pass_field = wait_for_element(self.driver, By.NAME, "password")
            if not pass_field:
                pass_field = wait_for_element(self.driver, By.ID, "password")
            pass_field.send_keys(password)

            # Enter school code (if separate field)
            try:
                school_field = self.driver.find_element(By.NAME, "schoolCode")
                school_field.send_keys(school_code)
            except:
                pass  # School code may be auto-filled or not required

            # Click login button
            login_btn = wait_for_clickable(self.driver, By.XPATH,
                "//button[contains(text(), 'Login') or @type='submit']")
            if login_btn:
                login_btn.click()

            # Wait for dashboard
            time.sleep(5)
            if "dashboard" in self.driver.current_url.lower() or "home" in self.driver.current_url.lower():
                self.logged_in = True
                print("✓ Successfully logged in!")
                return True
            else:
                print("❌ Login failed - check credentials")
                return False

        except Exception as e:
            print(f"❌ Login error: {str(e)}")
            return False

    def navigate_to_students(self):
        """Navigate to student data section"""
        print("📊 Navigating to student data...")

        # Try multiple navigation paths
        paths = [
            "//a[contains(text(), 'Student')]",
            "//a[contains(text(), 'Pupil')]",
            "//a[contains(@href, 'student')]",
            "//span[contains(text(), 'Student')]",
            "//*[contains(text(), 'Enrollment')]"
        ]

        for xpath in paths:
            try:
                element = self.driver.find_element(By.XPATH, xpath)
                element.click()
                time.sleep(3)
                print("✓ Found student section")
                return True
            except:
                continue

        print("⚠️  Could not auto-navigate. Please check portal structure.")
        return False

    def download_student_data(self):
        """Download student data from portal"""
        print("⬇️  Downloading student data...")

        ensure_directory(DEFAULT_DOWNLOAD_DIR)

        # Look for download/export buttons
        download_selectors = [
            "//button[contains(text(), 'Download')]",
            "//a[contains(text(), 'Export')]",
            "//button[contains(text(), 'Export')]",
            "//input[@type='button' and @value='Download']",
            "//a[contains(@href, 'download')]"
        ]

        downloaded = False
        for selector in download_selectors:
            try:
                buttons = self.driver.find_elements(By.XPATH, selector)
                for btn in buttons:
                    if btn.is_displayed():
                        btn.click()
                        time.sleep(5)
                        print("✓ Download initiated")
                        downloaded = True
                        break
                if downloaded:
                    break
            except:
                continue

        if not downloaded:
            print("⚠️  No download button found. Trying to scrape data from page...")
            return self.scrape_table_data()

        return True

    def scrape_table_data(self):
        """Scrape data from HTML tables on page"""
        print("📋 Scraping table data...")

        try:
            tables = self.driver.find_elements(By.TAG_NAME, "table")
            if not tables:
                print("❌ No tables found on page")
                return False

            print(f"Found {len(tables)} table(s)")

            for i, table in enumerate(tables):
                df = pd.read_html(table.get_attribute('outerHTML'))[0]
                filename = f"{DEFAULT_DOWNLOAD_DIR}/student_data_table_{i+1}_{datetime.now().strftime('%Y%m%d_%H%M')}.xlsx"
                df.to_excel(filename, index=False)
                print(f"✓ Saved: {filename}")

            return True

        except Exception as e:
            print(f"❌ Scraping error: {str(e)}")
            return False

    def create_master_excel(self):
        """Create a master Excel file with all student data"""
        print("📁 Creating master Excel file...")

        excel_file = os.path.join(DEFAULT_DOWNLOAD_DIR, "UDISE_Student_Master.xlsx")

        # Create template with multiple sheets
        with pd.ExcelWriter(excel_file, engine='openpyxl') as writer:
            # Sheet 1: Student Basic Info
            basic_info = pd.DataFrame(columns=[
                'UDISE_Code', 'Admission_No', 'Name', 'Father_Name',
                'Mother_Name', 'DOB', 'Gender', 'Caste', 'Category',
                'Aadhaar_No', 'Mobile_No', 'Email', 'Address'
            ])
            basic_info.to_excel(writer, sheet_name='Basic_Info', index=False)

            # Sheet 2: Academic Details
            academic = pd.DataFrame(columns=[
                'Admission_No', 'Class', 'Section', 'Roll_No',
                'Medium', 'Year', 'Previous_School', 'Transfer_Certificate_No'
            ])
            academic.to_excel(writer, sheet_name='Academic', index=False)

            # Sheet 3: Attendance
            attendance = pd.DataFrame(columns=[
                'Admission_No', 'Month', 'Working_Days',
                'Days_Present', 'Days_Absent', 'Attendance_Pct'
            ])
            attendance.to_excel(writer, sheet_name='Attendance', index=False)

            # Sheet 4: Fees
            fees = pd.DataFrame(columns=[
                'Admission_No', 'Fee_Type', 'Amount', 'Paid',
                'Due', 'Last_Payment_Date'
            ])
            fees.to_excel(writer, sheet_name='Fees', index=False)

        print(f"✓ Master Excel created: {excel_file}")
        return excel_file

    def generate_report_card(self, student_data):
        """Generate individual report cards"""
        print("📄 Generating report cards...")

        report_dir = os.path.join(DEFAULT_DOWNLOAD_DIR, "ReportCards")
        ensure_directory(report_dir)

        for _, student in student_data.iterrows():
            # Create simple HTML report card (you can enhance this)
            html_content = f"""
            <html>
            <head><title>Report Card - {student['Name']}</title></head>
            <body>
                <h1>Report Card</h1>
                <p><strong>Name:</strong> {student['Name']}</p>
                <p><strong>Admission No:</strong> {student['Admission_No']}</p>
                <p><strong>Class:</strong> {student.get('Class', 'N/A')}</p>
                <hr>
                <!-- Add more details here -->
            </body>
            </html>
            """
            filename = os.path.join(report_dir, f"report_{student['Admission_No']}.html")
            with open(filename, 'w') as f:
                f.write(html_content)

        print(f"✓ Report cards saved in: {report_dir}")

    def close(self):
        """Close browser"""
        if self.driver:
            self.driver.quit()
            print("✓ Browser closed")

# ─── Main Execution ────────────────────────────────────────────────────────────

def main():
    """Main function"""
    print("=" * 60)
    print("UDISE+ STUDENT DATA MANAGER")
    print("=" * 60)
    print()

    # Load saved config
    config = load_config()

    print("1. लॉगिन करने के लिए credentials दर्ज करें:")
    print("-" * 50)

    # Get username
    if 'username' in config:
        username = input(f"Username [{config['username']}]: ").strip()
        if not username:
            username = config['username']
    else:
        username = input("Username: ").strip()

    # Get password
    password = input("Password: ").strip()

    # Get school code
    if 'school_code' in config:
        school_code = input(f"School Code [{config['school_code']}]: ").strip()
        if not school_code:
            school_code = config['school_code']
    else:
        school_code = input("School Code (UDISE): ").strip()

    print()
    print("2. ब्राउज़र शुरू हो रहा है...")
    print("-" * 50)

    manager = UDISEPlusManager(headless=False)

    try:
        manager.setup_driver()

        # Login
        if manager.login(username, password, school_code):
            print()

            # Navigate to students
            if manager.navigate_to_students():
                print()

                # Download/Scrape data
                manager.download_student_data()
                print()

                # Create master Excel
                master_file = manager.create_master_excel()
                print()

                print("=" * 60)
                print("✓ PROCESS COMPLETE!")
                print("=" * 60)
                print(f"📁 Data saved in: {DEFAULT_DOWNLOAD_DIR}")
                print(f"📊 Master file: {master_file}")
                print()
                print("अब आप Excel file को open करके:")
                print("  • Student details देख सकते हैं")
                print("  • Updates/upgrades कर सकते हैं")
                print("  • New columns add कर सकते हैं")
                print("  • Reports जनरेट कर सकते हैं")
                print()
                print("अगर आपको आउटपुट में क्या चाहिए, वो बताइए!")
            else:
                print("❌ Student section नहीं मिला। Manual navigation needed.")
        else:
            print("❌ Login failed। Credentials check करें।")

    except KeyboardInterrupt:
        print("\n⚠️  Process interrupted by user")
    except Exception as e:
        print(f"❌ Error: {str(e)}")
    finally:
        manager.close()

if __name__ == "__main__":
    main()
