from datetime import date, timedelta
from uuid import uuid4

from app_new.extensions import db
from app_new.contracts.models import Contract, ContractVisit
from app_new.core.models.company import Part, PartStockMovement
from app_new.core.models.college import Building, Room
from app_new.core.models.equipment import Equipment, EquipmentCategory
from app_new.core.models.planning import Meter, MeterReading, Training, TrainingParticipant
from app_new.outlook.models import OutlookAccount, OutlookMail, OutlookMailInterpretation


def test_outlook_training_import_blocks_maintenance(authenticated_client, app, admin_user):
    with app.app_context():
        account = OutlookAccount(user_id=admin_user['id'], email='formation@example.test', tenant_id='test')
        mail = OutlookMail(id=f'mail-{uuid4().hex}', account=account, subject='Formation habilitation', sender='Rectorat')
        interpretation = OutlookMailInterpretation(
            mail=mail, user_id=admin_user['id'], interpretation='Formation détectée',
            analysis_type='formation', suggested_title='Habilitation électrique',
        )
        db.session.add_all([account, mail, interpretation]); db.session.commit()
        interpretation_id = interpretation.id
    day = date.today() + timedelta(days=10)
    with app.app_context():
        response = authenticated_client.post(f'/training/import/outlook/{interpretation_id}', data={
            'title': 'Habilitation électrique', 'start_date': day.isoformat(),
            'end_date': day.isoformat(), 'start_time': '09:00', 'end_time': '16:00',
        })
    assert response.status_code == 302
    with app.app_context():
        training = Training.query.filter_by(source_type='outlook', source_id=str(interpretation_id)).one()
        assert training.start_time.hour == 9
        assert TrainingParticipant.query.filter_by(training_id=training.id, user_id=admin_user['id'], is_confirmed=True).count() == 1
        db.session.delete(training)
        OutlookMailInterpretation.query.filter_by(id=interpretation_id).delete()
        OutlookMail.query.filter(OutlookMail.id.like('mail-%')).delete(synchronize_session=False)
        OutlookAccount.query.filter_by(user_id=admin_user['id']).delete(synchronize_session=False)
        db.session.commit()


def test_part_stock_movements_are_traced(authenticated_client, app):
    with app.app_context():
        part = Part(name=f'Lampe {uuid4().hex[:6]}', quantity=5, unit='unité')
        db.session.add(part); db.session.commit(); part_id = part.id
    with app.app_context():
        response = authenticated_client.post(f'/parts/{part_id}/movement', data={
            'movement_type': 'sortie', 'quantity': '2', 'reason': 'Intervention test',
        })
    assert response.status_code == 302
    with app.app_context():
        assert db.session.get(Part, part_id).quantity == 3
        movement = PartStockMovement.query.filter_by(part_id=part_id).one()
        assert (movement.quantity_before, movement.quantity_after) == (5, 3)


def test_contract_visits_are_generated_without_duplicates(authenticated_client, app):
    with app.app_context():
        contract = Contract(name=f'Contrat {uuid4().hex[:6]}', start_date=date.today(),
                            visit_interval_days=30, next_visit_date=date.today())
        db.session.add(contract); db.session.commit(); contract_id = contract.id
    with app.app_context():
        assert authenticated_client.post(f'/contracts/{contract_id}/visits/generate').status_code == 302
        assert authenticated_client.post(f'/contracts/{contract_id}/visits/generate').status_code == 302
    with app.app_context():
        visits = ContractVisit.query.filter_by(contract_id=contract_id).all()
        assert len(visits) >= 12
        assert len({visit.scheduled_date for visit in visits}) == len(visits)


def test_meter_decrease_requires_a_documented_reset(authenticated_client, app):
    with app.app_context():
        building = Building(name=f'Bâtiment {uuid4().hex[:6]}')
        room = Room(name='Local', building=building)
        category = EquipmentCategory(name=f'Catégorie {uuid4().hex[:6]}')
        equipment = Equipment(name='Compteur test', category=category, room=room)
        meter = Meter(name='Heures', equipment=equipment, current_value=100, initial_value=0)
        db.session.add_all([building, room, category, equipment, meter]); db.session.commit(); meter_id = meter.id
    with app.app_context():
        response = authenticated_client.post(f'/meters/{meter_id}/reading', data={'value': '10'})
    assert response.status_code == 302
    with app.app_context():
        assert db.session.get(Meter, meter_id).current_value == 100
    with app.app_context():
        authenticated_client.post(f'/meters/{meter_id}/reading', data={
            'value': '10', 'is_reset': '1', 'reset_reason': 'Compteur remplacé',
        })
    with app.app_context():
        assert db.session.get(Meter, meter_id).current_value == 10
        assert MeterReading.query.filter_by(meter_id=meter_id, is_reset=True).count() == 1
        MeterReading.query.filter_by(meter_id=meter_id).delete()
        db.session.commit()
