import os
import base64
from datetime import datetime
from io import BytesIO

from flask import Flask, redirect, request, jsonify
from flask_cors import CORS
from jinja2 import Environment, FileSystemLoader

from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
import smtplib
from dotenv import load_dotenv

# Suppress GLib-GIO warnings on Windows by redirecting stderr during import
import sys
from contextlib import redirect_stderr
with redirect_stderr(open(os.devnull, 'w')):
    from weasyprint import HTML

# For tours PDF generation
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas

load_dotenv()

app = Flask(__name__)

app.url_map.strict_slashes = False

# Updated CORS: Allow production domains and common local dev origins.
# IMPORTANT: Remove or comment out local origins before deploying to production!
CORS(app, resources={
    r"/*": {
        "origins": [
            "https://betheljuniorcampus.co.ke",
            "https://www.betheljuniorcampus.co.ke",
            # Local dev origins – REMOVE OR COMMENT THESE OUT BEFORE FINAL PRODUCTION DEPLOY!
            "http://localhost:8080",
            "http://localhost:3000",
            "http://localhost:5173",
            "http://127.0.0.1:3000",
            "http://127.0.0.1:5173",
            "http://127.0.0.1:8080"
        ],
        "methods": ["GET", "POST", "OPTIONS", "PUT", "DELETE"],
        "allow_headers": ["Content-Type", "Authorization"],
        "supports_credentials": False,
        "max_age": 3600  # Cache preflight response for 1 hour
    }
})
application = app  # For WSGI servers

# Set up Jinja2 for templating (used by admissions)
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
env = Environment(loader=FileSystemLoader(os.path.join(BASE_DIR, 'templates')))

# In-memory storage for tour requests (replace with database in production)
tour_requests = []


@app.route('/')
def index():
    return redirect("https://betheljuniorcampus.co.ke")

    
@app.route('/api/contact', methods=['POST'])
def contact():
    data = request.json
    name = data.get('name')
    email = data.get('email')
    subject = data.get('subject')
    message = data.get('message')

    if not all([name, email, subject, message]):
        return jsonify({'error': 'All fields (name, email, subject, message) are required.'}), 400

    # Compose the email body
    email_body = f"From: {name} <{email}>\n\n{message}"

    # Prepare the email message
    msg = MIMEText(email_body)
    msg['Subject'] = subject
    msg['From'] = os.getenv('SENDER_EMAIL_INFO', 'info@betheljuniorcampus.co.ke')
    msg['To'] = os.getenv('RECIPIENT_EMAIL_INFO', 'info@betheljuniorcampus.co.ke')

    try:
        # Connect to SMTP server - using webmail server
        server = smtplib.SMTP('lim110.truehost.cloud', 587)
        server.starttls()
        server.login(os.getenv('SENDER_EMAIL_INFO'), os.getenv('SENDER_PASSWORD'))
        server.send_message(msg)
        server.quit()

        return jsonify({}), 200
    except Exception as e:
        return jsonify({'error': str(e)}), 500

@app.route('/api/admissions', methods=['POST'])
def submit_admission():
    try:
        print("Received form data:", dict(request.form))
        print("Received files:", list(request.files.keys()))

        # Extract data
        pupil_first  = request.form.get('pupilFirstName', '').strip()
        pupil_middle = request.form.get('pupilMiddleName', '').strip()
        pupil_last   = request.form.get('pupilLastName', '').strip()
        pupil_name   = f"{pupil_first} {pupil_middle} {pupil_last}".strip() or "Unknown Pupil"

        dob_year = request.form.get('dobYear', '').strip()
        dob_month = request.form.get('dobMonth', '').strip()
        dob_day = request.form.get('dobDay', '').strip()
        if dob_year:
            dob = f"{dob_year}-{dob_month.zfill(2)}-{dob_day.zfill(2)}"
        else:
            dob = "Not provided"

        gender        = request.form.get('gender', '').strip() or 'Not provided'
        grade         = request.form.get('grade', '').strip() or 'Not specified'
        accommodation = request.form.get('accommodationType', '').strip() or 'Not specified'
        place_of_birth = request.form.get('placeOfBirth', '').strip() or 'Not provided'
        nationality   = request.form.get('nationality', '').strip() or 'Not provided'
        first_language = request.form.get('firstLanguage', '').strip() or 'Not provided'
        other_language = request.form.get('otherLanguages', '').strip() or 'Not provided'
        current_residence = request.form.get('currentResidence', '').strip() or 'Not provided'
        upi_number    = request.form.get('upiNumber', '').strip() or 'Not provided'
        assesment_number = request.form.get('assessmentNumber', '') or 'Not provided'

        
        # father name
        father_first  = request.form.get('fatherFirstName', '').strip()
        father_middle = request.form.get('fatherMiddleName', '').strip()
        father_last   = request.form.get('fatherLastName', '').strip()

        #mother name
        mother_first  = request.form.get('motherFirstName', '').strip()
        mother_middle = request.form.get('motherMiddleName', '').strip()
        mother_last   = request.form.get('motherLastName', '').strip()

        #guardian name
        guardian_first  = request.form.get('guardianFirstName', '').strip()
        guardian_middle = request.form.get('guardianMiddleName', '').strip()
        guardian_last   = request.form.get('guardianLastName', '').strip()

        #full names
        father_name   = f"{father_first} {father_middle} {father_last}".strip() or "Unknown Parent"
        mother_name   = f"{mother_first} {mother_middle} {mother_last}".strip() or "Unknown Parent"
        guardian_name = f"{guardian_first} {guardian_middle} {guardian_last}".strip() or "Unknown Guardian"
    
        # email info
        father_email = request.form.get('fatherEmail', '').strip() or 'No email provided'
        mother_email = request.form.get('motherEmail', '').strip() or 'No email provided'
        guardian_email = request.form.get('guardianEmail', '').strip() or 'No email provided'

      
        
        # phone details
        father_phone = request.form.get('fatherPhone', '').strip() or 'Not provided'
        mother_phone = request.form.get('motherPhone', '').strip() or 'Not provided'
        



        # profession info

        father_profession = request.form.get('fatherProfession', '').strip() or 'Not provided'
        mother_profession = request.form.get('motherProfession', '').strip() or 'Not provided'
        
        # country info
        father_county = request.form.get('fatherCounty', '').strip() or 'Not provided'
        mother_county = request.form.get('motherCounty', '').strip() or 'Not provided'
        
        # subcounty info
        father_subcounty = request.form.get('fatherSubCounty', '').strip() or 'Not provided'
        mother_subcounty = request.form.get('motherSubCounty', '').strip() or 'Not provided'

        # parents id   
        father_id = request.form.get('fatherIdNo', '').strip() or 'Not provided'
        mother_id = request.form.get('motherIdNo', '').strip() or 'Not provided'


        # guardian info
        guardian_relationship = request.form.get('guardianRelation', '').strip() or 'Not provided'
        guardian_profession = request.form.get('guardianProfession', '').strip() or 'Not provided'
        guardian_county = request.form.get('guardianCounty', '').strip() or 'Not provided'
        guardian_subcounty = request.form.get('guardianSubCounty', '').strip() or 'Not provided'
        guardian_phone = request.form.get('guardianPhone', '').strip() or 'Not provided'
        guardian_id = request.form.get('guardianIdNo', '').strip() or 'Not provided'
        
        # emergency info
        emergency = request.form.get('emergency1', '').strip() or 'Not provided'
        emergency2 = request.form.get('emergency2', '').strip() or 'Not provided'
        emergency3 = request.form.get('emergency3', '').strip() or 'Not provided'
        medical_info = request.form.get('medicalConditions', '').strip() or 'Not provided'


        if not pupil_name.strip():
            return jsonify({'error': 'Missing critical information'}), 400

        # Check required documents
        required_files = ['parentIdPhotocopy', 'birthCertificate', 'passportPhotos']
        missing_files = []
        for field in required_files:
            file = request.files.get(field)
            if not file or not file.filename:
                missing_files.append(field)
        
        if missing_files:
            return jsonify({'error': f'Missing required documents: {", ".join(missing_files)}'}), 400
        


        logo_path = os.path.join(BASE_DIR, 'static', 'school-logo.png')
        if os.path.exists(logo_path):
            with open(logo_path, 'rb') as img_file:
                logo_base64 = base64.b64encode(img_file.read()).decode('utf-8')
                logo_data_url = f'data:image/png;base64,{logo_base64}'
        else:
            logo_data_url = ''
            print(f"Warning: Logo not found at {logo_path}")

        # Render HTML template for PDF
        template = env.get_template('admission_report.html')
        html_content = template.render(

            logo_data_url=logo_data_url,
            pupil_name=pupil_name,
            dob=dob,
            gender=gender,
            grade=grade,
            accommodation=accommodation,
            place_of_birth=place_of_birth,
            nationality=nationality,
            first_language=first_language,
            other_language=other_language,
            current_residence=current_residence,
            upi_number=upi_number,
            assesment_number=assesment_number,

            # parent info
            father_name=father_name,
            mother_name=mother_name,
            father_email=father_email,
            mother_email=mother_email,
            father_phone=father_phone,
            mother_phone=mother_phone,
            father_profession=father_profession,
            mother_profession=mother_profession,
            father_county=father_county,
            mother_county=mother_county,
            father_subcounty=father_subcounty,
            mother_subcounty=mother_subcounty,
            father_id=father_id,
            mother_id=mother_id,
            
            # guardian info
            guardian_name   =guardian_name,
            guardian_email=guardian_email,
            guardian_phone=guardian_phone,
            guardian_id=guardian_id,   
            guardian_county=guardian_county,
            guardian_subcounty=guardian_subcounty,
            guardian_relationship=guardian_relationship,
            guardian_profession=guardian_profession,

            emergency=emergency,
            emergency2=emergency2,  
            emergency3=emergency3,
            medical_info=medical_info,

            submission_date=datetime.now().strftime("%Y-%m-%d %H:%M")
        )

        # Generate PDF in memory
        pdf_io = BytesIO()
        with redirect_stderr(open(os.devnull, 'w')):
            HTML(string=html_content).write_pdf(pdf_io)
        pdf_io.seek(0)

        # Email setup
        sender_email    = os.getenv('SENDER_EMAIL')
        sender_password = os.getenv('SENDER_PASSWORD')
        recipient_email = os.getenv('RECIPIENT_EMAIL')

        if not all([sender_email, sender_password, recipient_email]):
            print("Missing email config in .env")
            return jsonify({'error': 'Server configuration error'}), 500

        # All possible documents
        all_documents = {
            'parentIdPhotocopy': 'Parent ID Photocopy',
            'birthCertificate': 'Birth Certificate',
            'passportPhotos': 'Passport Photos',
            'medicalForm': 'Medical Form',
            'transferCertificate': 'Transfer Certificate'
        }

        # Build email
        msg = MIMEMultipart()
        msg['From']    = sender_email
        msg['To']      = recipient_email
        msg['Subject'] = f"New Admission Enquiry – {pupil_name} (Grade: {grade})"

        attached_docs = []

        # Attach the generated PDF
        pdf_attachment = MIMEBase('application', 'pdf')
        pdf_attachment.set_payload(pdf_io.read())
        encoders.encode_base64(pdf_attachment)
        pdf_attachment.add_header(
            'Content-Disposition',
            f'attachment; filename="Admission {pupil_name.replace(" ", "_")}.pdf"'
        )
        msg.attach(pdf_attachment)
        attached_docs.append('Admission Report PDF')

        # Attach original documents
        for field_name, display_name in all_documents.items():
            file = request.files.get(field_name)
            if file and file.filename:
                attachment = MIMEBase('application', 'octet-stream')
                attachment.set_payload(file.read())
                encoders.encode_base64(attachment)
                attachment.add_header(
                    'Content-Disposition',
                    f'attachment; filename="{file.filename}"'
                )
                msg.attach(attachment)
                print(f"Attached: {display_name} ({file.filename})")
                attached_docs.append(display_name)
            else:
                print(f"No file for {display_name}")

        attached_str = '\n  • ' + '\n  • '.join(attached_docs) if attached_docs else '\n  • None'

        body = f"""\
New Admission Application Received

Attached documents:{attached_str}

Please review the attached files for full details.
"""
        msg.attach(MIMEText(body, 'plain'))

        # Send using webmail server
        with smtplib.SMTP('lim110.truehost.cloud', 587) as server:
            server.starttls()
            server.login(sender_email, sender_password)
            server.send_message(msg)


        return jsonify({'message': 'Application received successfully'}), 200

    except Exception as e:
        print(f"ERROR: {str(e)}")
        return jsonify({'error': str(e) or 'Server error – please try again'}), 500

@app.route('/api/careers', methods=['POST'])
def submit_application():
    try:
        print("Content-Type:", request.content_type)
        print("Received form data:", dict(request.form))
        print("Received files:", list(request.files.keys()))

        # Extract data
        name = request.form.get('name', '').strip() or 'Unknown Applicant'
        email = request.form.get('email', '').strip() or 'No email provided'
        phone = request.form.get('phone', '').strip() or 'Not provided'
        cover_letter = request.form.get('coverLetter', '').strip() or 'Not provided'
        position = request.form.get('position', 'General Application').strip()

        # Check required file
        cv_file = request.files.get('cv')
        if not cv_file or not cv_file.filename:
            return jsonify({'error': 'Missing CV file'}), 400

        # Validate file type (optional, but good practice)
        allowed_extensions = {'pdf', 'doc', 'docx'}
        if '.' not in cv_file.filename or cv_file.filename.rsplit('.', 1)[1].lower() not in allowed_extensions:
            return jsonify({'error': 'Invalid file type. Only PDF or Word documents allowed.'}), 400

        logo_path = os.path.join(BASE_DIR, 'static', 'school-logo.png')
        if os.path.exists(logo_path):
            with open(logo_path, 'rb') as img_file:
                logo_base64 = base64.b64encode(img_file.read()).decode('utf-8')
                logo_data_url = f'data:image/png;base64,{logo_base64}'
        else:
            logo_data_url = ''
            print(f"Warning: Logo not found at {logo_path}")

        # Render HTML template for PDF
        template = env.get_template('application_report.html')
        html_content = template.render(
            logo_data_url=logo_data_url,
            name=name,
            email=email,
            phone=phone,
            cover_letter=cover_letter,
            submission_date=datetime.now().strftime("%Y-%m-%d %H:%M")
        )

        # Generate PDF in memory
        pdf_io = BytesIO()
        with redirect_stderr(open(os.devnull, 'w')):
            HTML(string=html_content).write_pdf(pdf_io)
        pdf_io.seek(0)

        # Email setup
        sender_email = os.getenv('SENDER_EMAIL_CAR')
        sender_password = os.getenv('SENDER_PASSWORD')
        recipient_email = os.getenv('RECIPIENT_EMAIL_CAR')

        if not all([sender_email, sender_password, recipient_email]):
            print("Missing email config in .env")
            return jsonify({'error': 'Server configuration error'}), 500

        # Build email
        msg = MIMEMultipart()
        msg['From'] = sender_email
        msg['To'] = recipient_email
        msg['Subject'] = f"New Job Application for {position} – {name}"

        attached_docs = []

        # Attach the generated PDF
        pdf_attachment = MIMEBase('application', 'pdf')
        pdf_attachment.set_payload(pdf_io.read())
        encoders.encode_base64(pdf_attachment)
        pdf_attachment.add_header(
            'Content-Disposition',
            f'attachment; filename="Application_{name.replace(" ", "_")}.pdf"'
        )
        msg.attach(pdf_attachment)
        attached_docs.append('Application Report PDF')

        # Attach CV
        cv_attachment = MIMEBase('application', 'octet-stream')
        cv_attachment.set_payload(cv_file.read())
        encoders.encode_base64(cv_attachment)
        cv_attachment.add_header(
            'Content-Disposition',
            f'attachment; filename="{cv_file.filename}"'
        )
        msg.attach(cv_attachment)
        attached_docs.append('CV')

        attached_str = '\n • ' + '\n • '.join(attached_docs) if attached_docs else '\n • None'

 

        # Send using webmail server
        with smtplib.SMTP('lim110.truehost.cloud', 587) as server:
            server.starttls()
            server.login(sender_email, sender_password)
            server.send_message(msg)

        return jsonify({'message': 'Application received successfully'}), 200

    except Exception as e:
        print(f"ERROR: {str(e)}")
        return jsonify({'error': str(e) or 'Server error – please try again'}), 500

@app.route('/api/tours', methods=['POST'])
def book_tour():
    try:
        data = request.get_json()
        
        required = ['name', 'email', 'phone', 'studentAge', 'date', 'timeSlot']
        if not all(field in data for field in required):
            return jsonify({'error': 'Missing required fields'}), 400
        
        # Format date nicely
        try:
            tour_date = datetime.fromisoformat(data['date'].replace('Z', '+00:00')).strftime('%Y-%m-%d')
        except:
            tour_date = data['date']
        
        tour_data = {
            'name': data['name'],
            'email': data['email'],
            'phone': data['phone'],
            'studentAge': data['studentAge'],
            'tourDate': tour_date,
            'timeSlot': data['timeSlot'],
            'message': data.get('message', ''),
            'createdAt': datetime.now().isoformat()
        }
        
        # 1. Save to in-memory list (replace with DB in production)
        tour_requests.append(tour_data)
        
        logo_path = os.path.join(BASE_DIR, 'static', 'school-logo.png')
        if os.path.exists(logo_path):
            with open(logo_path, 'rb') as img_file:
                logo_base64 = base64.b64encode(img_file.read()).decode('utf-8')
                logo_data_url = f'data:image/png;base64,{logo_base64}'
        else:
            logo_data_url = ''
            print(f"Warning: Logo not found at {logo_path}")

        # 2. Generate PDF
        tour = env.get_template('tour.html')
        html_content = tour.render(
            logo_data_url=logo_data_url,
            name=tour_data['name'],
            email=tour_data['email'],
            phone=tour_data['phone'],
            studentAge=tour_data['studentAge'],
            tourDate=tour_data['tourDate'],
            timeSlot=tour_data['timeSlot'],
            message=tour_data['message'] or 'None',
            submission_date=datetime.now().strftime("%Y-%m-%d %H:%M")
        )

        pdf = BytesIO()
        with redirect_stderr(open(os.devnull, 'w')):
            HTML(string=html_content).write_pdf(pdf)
        pdf.seek(0)
        
        # 3. Prepare email
        sender_email = os.getenv('SENDER_EMAIL_INFO')
        sender_password = os.getenv('SENDER_PASSWORD')
        recipient_email = os.getenv('RECIPIENT_EMAIL_INFO')

        if not all([sender_email, sender_password, recipient_email]):
            print("Missing email config in .env")
            return jsonify({'error': 'Server configuration error'}), 500


        msg = MIMEMultipart()
        msg['From'] = sender_email
        msg['To'] = recipient_email
        msg['Subject'] = f"New Tour Booking: {tour_data['name']}";
        
        
        
        # Attach PDF
        # Attach the generated PDF
        attached_docs = []
        part = MIMEBase('application', "octet-stream")
        pdf_attachment = MIMEBase('application', 'pdf')
        pdf_attachment.set_payload(pdf.read())
        encoders.encode_base64(pdf_attachment)
        pdf_attachment.add_header(
            'Content-Disposition',
            f'attachment; filename="Booking_tour:{tour_data["name"].replace(" ", "_")}.pdf"'
        )
        msg.attach(pdf_attachment)
        attached_docs.append('Tour_Booking PDF')
        
        
        # Send email using webmail server
        server = smtplib.SMTP('lim110.truehost.cloud', 587)
        server.starttls()
        server.login(sender_email, sender_password)
        server.send_message(msg)
        server.quit()
        
        return jsonify({
            "message": "Tour request submitted successfully",
            "data": tour_data
        }), 201
        
    except Exception as e:
        print(f"Tour booking error: {e}")
        return jsonify({"error": "Failed to book tour"}), 500

@app.route('/api/tours', methods=['GET'])
def get_all_tours():
    # For admin - return all requests
    return jsonify(tour_requests), 200

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000, debug=True)