"""Payroll profile, run lifecycle, expense integration, and isolation."""
from datetime import date
from decimal import Decimal
import uuid
from sqlalchemy import delete, select
from app.core.security import create_access_token, hash_password
from app.db.session import SessionLocal
from app.models.membership import Membership
from app.models.user import User
from tests.test_workspace import _headers, _payload, client, verified_user

def _workspace(client, user, name="Payroll Store"):
    response=client.post('/api/businesses/onboarding',json=_payload(name),headers=_headers(user)); assert response.status_code==201
    return response.json()['business']['id'], response.json()['membership']['id']
def _profile(client, headers, business_id, membership_id, salary='1000.00'):
    r=client.post(f'/api/businesses/{business_id}/payroll/profiles',json={'membership_id':membership_id,'salary':salary,'payment_frequency':'MONTHLY'},headers=headers); assert r.status_code==201,r.text; return r.json()
def _run(client, headers, business_id, membership_id, profile_id, adjustment='0', start='2026-01-01', end='2026-01-31'):
    return client.post(f'/api/businesses/{business_id}/payroll/runs',json={'membership_id':membership_id,'payroll_profile_id':profile_id,'period_start':start,'period_end':end,'adjustment_amount':adjustment,'adjustment_note':'Adjustment' if adjustment!='0' else None},headers=headers)

def test_payroll_lifecycle_snapshot_duplicate_and_expense(client, verified_user):
    headers=_headers(verified_user); business_id,membership_id=_workspace(client,verified_user)
    profile=_profile(client,headers,business_id,membership_id)
    created=_run(client,headers,business_id,membership_id,profile['id'],'25.00'); assert created.status_code==201,created.text
    run=created.json(); assert run['base_salary']=='1000.00' and run['total_amount']=='1025.00' and run['status']=='DRAFT'
    changed=client.patch(f"/api/businesses/{business_id}/payroll/profiles/{profile['id']}",json={'salary':'2000.00'},headers=headers); assert changed.status_code==200
    assert client.get(f"/api/businesses/{business_id}/payroll/runs/{run['id']}",headers=headers).json()['base_salary']=='1000.00'
    assert _run(client,headers,business_id,membership_id,profile['id'],'0').status_code==422
    assert _run(client,headers,business_id,membership_id,profile['id'],'-2500.00',start='2026-02-01',end='2026-02-28').status_code==422
    assert client.post(f"/api/businesses/{business_id}/payroll/runs/{run['id']}/pay",json={'payment_method':'CASH'},headers=headers).status_code==422
    approved=client.post(f"/api/businesses/{business_id}/payroll/runs/{run['id']}/approve",headers=headers); assert approved.status_code==200
    assert client.post(f"/api/businesses/{business_id}/payroll/runs/{run['id']}/approve",headers=headers).status_code==422
    paid=client.post(f"/api/businesses/{business_id}/payroll/runs/{run['id']}/pay",json={'payment_method':'TRANSFER'},headers=headers); assert paid.status_code==200,paid.text
    body=paid.json(); assert body['status']=='PAID' and body['expense_id'] and body['payment_method']=='TRANSFER'
    expense=client.get(f"/api/businesses/{business_id}/expenses/{body['expense_id']}",headers=headers); assert expense.status_code==200 and Decimal(str(expense.json()['amount']))==Decimal('1025.00') and expense.json()['payment_method']=='TRANSFER'
    assert client.post(f"/api/businesses/{business_id}/payroll/runs/{run['id']}/pay",json={'payment_method':'TRANSFER'},headers=headers).status_code==422
    assert client.post(f"/api/businesses/{business_id}/payroll/runs/{run['id']}/cancel",headers=headers).status_code==422

def test_payroll_isolation_inactive_target_and_unauthorized_salary(client, verified_user):
    headers=_headers(verified_user); business_id,membership_id=_workspace(client,verified_user)
    db=SessionLocal(); user=User(full_name='Cashier',email=f'cashier-{uuid.uuid4().hex}@example.com',password_hash=hash_password('TestPassword123!'),is_email_verified=True); db.add(user);db.flush(); cashier=Membership(business_id=uuid.UUID(business_id),user_id=user.id,role='CASHIER',is_active=True); db.add(cashier);db.commit();db.refresh(user)
    try:
        cashier_headers={'Authorization':f'Bearer {create_access_token(str(user.id))}'}
        assert client.post(f'/api/businesses/{business_id}/payroll/profiles',json={'membership_id':membership_id,'salary':'100','payment_frequency':'MONTHLY'},headers=cashier_headers).status_code==403
        profile=_profile(client,headers,business_id,membership_id)
        db.execute(delete(Membership).where(Membership.id==cashier.id)); db.commit()
        db.execute(Membership.__table__.update().where(Membership.id==uuid.UUID(membership_id)).values(is_active=False));db.commit()
        assert _run(client,headers,business_id,membership_id,profile['id']).status_code==404
    finally:
        db.execute(delete(User).where(User.id==user.id));db.commit();db.close()
