import click,requests,json
from flask.cli import with_appcontext
from datetime import datetime, timedelta, date
from sqlalchemy import and_
from extensions import db
from models import Attendance, Employee, PublicHoliday, LeaveRequest, DesktimeLog, WeekendSettings, SyncLog


DESKTIME_API_KEY = "f9da2cfcf20ff9508002b5a74aa0ff59"
DESKTIME_URL = "https://desktime.com/api/v2/json/employee"


def fetch_and_store_desktime(employee, target_date):
    formatted_date = target_date.strftime('%Y-%m-%d')
    url = f"{DESKTIME_URL}?apiKey={DESKTIME_API_KEY}&id={employee.desktime_id}&date={formatted_date}"

    try:
        response = requests.get(url)
        if response.status_code == 200:
            data = response.json()

            productive_seconds = data.get('productiveTime', 0)
            first_login = data.get('arrived')
            last_logout = data.get('left')

            log = DesktimeLog.query.filter_by(employee_id=employee.id, date=target_date).first()
            if not log:
                log = DesktimeLog(employee_id=employee.id, date=target_date)

            log.first_activity = datetime.strptime(first_login, '%Y-%m-%d %H:%M:%S').time() if first_login else None
            log.last_activity = datetime.strptime(last_logout, '%Y-%m-%d %H:%M:%S').time() if last_logout else None
            log.productive_hours = productive_seconds / 3600 if productive_seconds else 0
            log.raw_data = json.dumps(data)

            db.session.add(log)
            db.session.commit()

            return log.productive_hours
        else:
            print(f"\u26a0\ufe0f Desktime API failed for {employee.desktime_id} on {formatted_date}: Status {response.status_code}")
    except Exception as e:
        print(f"\u274c Error fetching Desktime for {employee.employee_code} on {formatted_date}: {e}")

    return 0

# ... (imports and setup remain same)

@click.command('process-attendance')
@with_appcontext
def process_attendance():
    today = date.today()
    fy_start = today.replace(month=4, day=1) if today.month >= 4 else date(today.year - 1, 4, 1)
    fy_end = fy_start.replace(year=fy_start.year + 1) - timedelta(days=1)

    employees = Employee.query.filter_by(status='active').all()
    weekend_settings = WeekendSettings.query.order_by(WeekendSettings.updated_on.desc()).first()

    def is_saturday_off(day):
        if day.weekday() != 5:
            return False
        week_number = (day.day - 1) // 7 + 1
        attr = f"{['first', 'second', 'third', 'fourth', 'fifth'][week_number - 1]}_saturday"
        return getattr(weekend_settings, attr) == 'off'

    def is_sunday_off(day):
        return day.weekday() == 6 and weekend_settings.sunday == 'off'

    for emp in employees:
        for single_date in (fy_start + timedelta(n) for n in range((fy_end - fy_start).days + 1)):

            if single_date > today:
                continue  # ⛔ Skip future dates

            is_weekend = is_saturday_off(single_date) or is_sunday_off(single_date)
            is_holiday = PublicHoliday.query.filter_by(date=single_date).first() is not None
            is_leave = LeaveRequest.query.filter_by(employee_id=emp.id, status='final_approved')\
                .filter(LeaveRequest.start_date <= single_date, LeaveRequest.end_date >= single_date).first() is not None

            existing = Attendance.query.filter_by(employee_id=emp.id, date=single_date).first()

            # ✅ If Desktime entry already exists, skip (unless you're explicitly reprocessing)
            if existing and existing.source == 'Desktime':
                continue

            hours = 0
            source = 'System'

            if is_holiday:
                remark = 'Holiday'
                source = 'Holiday'
            elif is_leave:
                remark = 'Leave'
                source = 'Leave'
            elif is_weekend:
                remark = 'Holiday'
                source = 'Weekend'
            else:
                if existing and existing.check_in_time and existing.check_out_time:
                    diff = datetime.combine(date.min, existing.check_out_time) - datetime.combine(date.min, existing.check_in_time)
                    hours = round(diff.total_seconds() / 3600, 2)
                    source = 'Punch'
                elif emp.desktime_id:
                    hours = fetch_and_store_desktime(emp, single_date)
                    if hours > 0:
                        source = 'Desktime'

                if hours >= 7:
                    remark = 'Present'
                elif 3.5 <= hours < 7:
                    remark = 'Half Day'
                elif 0 < hours < 3.5:
                    remark = 'LWP'
                else:
                    remark = 'LWP'

            if existing:
                existing.working_hours = hours
                existing.remarks = remark
                existing.source = source
            else:
                db.session.add(Attendance(
                    employee_id=emp.id,
                    date=single_date,
                    check_in_time=None,
                    check_out_time=None,
                    working_hours=hours,
                    remarks=remark,
                    source=source
                ))

    db.session.commit()
    click.echo("✅ Attendance processing complete.")


@click.command('desktime-sync')
@with_appcontext
def desktime_sync():
    # Adjust the import path as needed based on your project structure
    from utils.desktime import sync_all_desktime_data  # replace with your actual sync function

    log = SyncLog(started_at=datetime.now(), status='Started')
    db.session.add(log)
    db.session.commit()

    try:
        result = sync_all_desktime_data()
        log.status = 'Completed'
        log.message = f"Synced: {result.get('synced', 0)}, Errors: {result.get('errors', 0)}"
    except Exception as e:
        log.status = 'Failed'
        log.message = str(e)
    finally:
        log.ended_at = datetime.now()
        db.session.commit()