"""Delivery lifecycle, tenant boundaries, and branch access."""
import uuid
from sqlalchemy import delete
from app.core.security import create_access_token, hash_password
from app.db.session import SessionLocal
from app.models.branch import Branch
from app.models.business import Business
from app.models.customer import Customer
from app.models.membership import Membership, MembershipBranch
from app.models.sale import Sale
from app.models.user import User
from tests.test_workspace import _headers, _payload, client, verified_user

def workspace(client, user, name="Delivery Store"):
    r=client.post('/api/businesses/onboarding',json=_payload(name),headers=_headers(user)); assert r.status_code==201
    return r.json()['business']['id'],r.json()['accessible_branches'][0]['id']
def customer(client, headers, business):
    r=client.post(f'/api/businesses/{business}/customers',json={'name':'Delivery Customer','address':'1 Delivery Road'},headers=headers);assert r.status_code==201;return r.json()['id']
def create(client, headers, business, branch, customer_id, **extra):
    payload={'branch_id':branch,'customer_id':customer_id,'address':'1 Delivery Road','delivery_fee':'250.00','tracking_reference':'TRACK-1'}|extra
    return client.post(f'/api/businesses/{business}/deliveries',json=payload,headers=headers)

def test_delivery_create_update_transition_history_and_filters(client,verified_user):
    h=_headers(verified_user); b,branch=workspace(client,verified_user); c=customer(client,h,b)
    made=create(client,h,b,branch,c);assert made.status_code==201,made.text; d=made.json();assert d['status']=='PENDING' and d['delivery_fee']=='250.00'
    assert len(client.get(f'/api/businesses/{b}/deliveries?branch_id={branch}&customer_id={c}&status_filter=PENDING',headers=h).json())==1
    edit=client.patch(f"/api/businesses/{b}/deliveries/{d['id']}",json={'notes':'Packed'},headers=h);assert edit.status_code==200 and edit.json()['notes']=='Packed'
    transit=client.post(f"/api/businesses/{b}/deliveries/{d['id']}/status",json={'status':'IN_TRANSIT','note':'Collected'},headers=h);assert transit.status_code==200
    done=client.post(f"/api/businesses/{b}/deliveries/{d['id']}/status",json={'status':'DELIVERED'},headers=h);assert done.status_code==200 and done.json()['status']=='DELIVERED'
    assert client.patch(f"/api/businesses/{b}/deliveries/{d['id']}",json={'notes':'No'},headers=h).status_code==422
    assert client.post(f"/api/businesses/{b}/deliveries/{d['id']}/status",json={'status':'PENDING'},headers=h).status_code==422
    history=client.get(f"/api/businesses/{b}/deliveries/{d['id']}/history",headers=h);assert history.status_code==200 and [x['new_status'] for x in history.json()]==['PENDING','IN_TRANSIT','DELIVERED']

def test_delivery_cancel_wrong_business_and_isolation(client,verified_user):
    h=_headers(verified_user); b,branch=workspace(client,verified_user); c=customer(client,h,b)
    d=create(client,h,b,branch,c); assert d.status_code==201
    cancelled=client.post(f"/api/businesses/{b}/deliveries/{d.json()['id']}/status",json={'status':'CANCELLED'},headers=h);assert cancelled.status_code==200
    assert client.post(f"/api/businesses/{b}/deliveries/{d.json()['id']}/status",json={'status':'IN_TRANSIT'},headers=h).status_code==422
    other=client.post('/api/businesses',json=_payload('Other'),headers={**h,'Idempotency-Key':'delivery-other'}).json(); ob=other['business']['id']; obranch=other['accessible_branches'][0]['id']; oc=customer(client,h,ob)
    assert create(client,h,b,obranch,c).status_code==422
    assert create(client,h,b,branch,oc).status_code==422
    assert client.get(f"/api/businesses/{ob}/deliveries/{d.json()['id']}",headers=h).status_code==404

def test_delivery_sale_validation_branch_membership_inactive_and_unauthenticated(client,verified_user):
    h=_headers(verified_user); b,branch=workspace(client,verified_user); c=customer(client,h,b)
    db=SessionLocal(); other_business=Business(name='Foreign'); db.add(other_business);db.flush(); foreign_branch=Branch(business_id=other_business.id,name='Foreign Branch');foreign_customer=Customer(business_id=other_business.id,name='Foreign Customer');db.add_all([foreign_branch,foreign_customer]);db.flush(); foreign_sale=Sale(business_id=other_business.id,branch_id=foreign_branch.id,customer_id=foreign_customer.id,receipt_number='foreign',payment_status='PAID',subtotal=0,discount=0,tax=0,total=0,amount_paid=0,balance=0,created_by=verified_user.id);db.add(foreign_sale);db.commit()
    try:
        assert create(client,h,b,branch,c,sale_id=str(foreign_sale.id)).status_code==422
        db.execute(Membership.__table__.update().where(Membership.business_id==uuid.UUID(b)).values(is_active=False));db.commit()
        assert create(client,h,b,branch,c).status_code==404
        assert client.post(f'/api/businesses/{b}/deliveries',json={'branch_id':branch,'customer_id':c,'address':'x','tracking_reference':'t'}).status_code==401
    finally:
        db.execute(delete(Sale).where(Sale.id==foreign_sale.id));db.execute(delete(Customer).where(Customer.id==foreign_customer.id));db.execute(delete(Branch).where(Branch.id==foreign_branch.id));db.execute(delete(Business).where(Business.id==other_business.id));db.commit();db.close()
