from datetime import timedelta

import jwt
from django.conf import settings
from django.utils import timezone
from rest_framework.test import APITestCase

from core.models import User
from disputes.models import Dispute

from .models import Deal


class DealApiTests(APITestCase):
	deals_url = "/api/v1/deals"

	def setUp(self):
		super().setUp()
		self.seller = User.objects.create(phone="+255700100001", role=User.Role.SELLER)
		self.buyer = User.objects.create(phone="+255700100002", role=User.Role.BUYER)

	def _token_for_user(self, user):
		return jwt.encode(
			{
				"sub": str(user.id),
				"phone": user.phone,
				"role": user.role,
				"type": "access",
				"iat": int(timezone.now().timestamp()),
				"exp": int((timezone.now() + timedelta(minutes=60)).timestamp()),
			},
			settings.JWT_SECRET_KEY,
			algorithm=settings.JWT_ALGORITHM,
		)

	def _auth_headers(self, user):
		return {"HTTP_AUTHORIZATION": f"Bearer {self._token_for_user(user)}"}

	def test_create_deal_generates_shareable_code(self):
		response = self.client.post(
			self.deals_url,
			{
				"title": "Laptop Sale",
				"description": "Macbook M2",
				"amount": "1200000.00",
				"inspection_window_hours": 72,
			},
			format="json",
			**self._auth_headers(self.seller),
		)

		self.assertEqual(response.status_code, 201)
		self.assertEqual(response.data["status"], Deal.Status.DRAFT)
		self.assertEqual(len(response.data["code"]), 8)

	def test_join_deal_by_code_sets_buyer_and_awaiting_payment(self):
		deal = Deal.objects.create(
			seller=self.seller,
			code="KP2A8BX1",
			title="Phone",
			description="Phone sale",
			amount="500000.00",
			fee="0.00",
			net_amount="500000.00",
			status=Deal.Status.DRAFT,
		)

		response = self.client.post(
			f"/api/v1/deals/{deal.code}/join",
			{},
			format="json",
			**self._auth_headers(self.buyer),
		)

		self.assertEqual(response.status_code, 200)
		deal.refresh_from_db()
		self.assertEqual(deal.buyer_id, self.buyer.id)
		self.assertEqual(deal.status, Deal.Status.AWAITING_PAYMENT)

	def test_full_status_flow_fund_ship_confirm(self):
		deal = Deal.objects.create(
			seller=self.seller,
			buyer=self.buyer,
			code="ABCD1234",
			title="Watch",
			description="Smart watch",
			amount="100000.00",
			fee="0.00",
			net_amount="100000.00",
			status=Deal.Status.AWAITING_PAYMENT,
		)

		fund_response = self.client.post(
			f"/api/v1/deals/{deal.id}/fund",
			{},
			format="json",
			**self._auth_headers(self.buyer),
		)
		self.assertEqual(fund_response.status_code, 200)
		self.assertEqual(fund_response.data["status"], Deal.Status.FUNDED)

		ship_response = self.client.post(
			f"/api/v1/deals/{deal.id}/ship",
			{"tracking_info": "TRK-1"},
			format="json",
			**self._auth_headers(self.seller),
		)
		self.assertEqual(ship_response.status_code, 200)
		self.assertEqual(ship_response.data["status"], Deal.Status.IN_TRANSIT)

		confirm_response = self.client.post(
			f"/api/v1/deals/{deal.id}/confirm",
			{},
			format="json",
			**self._auth_headers(self.buyer),
		)
		self.assertEqual(confirm_response.status_code, 200)
		self.assertEqual(confirm_response.data["status"], Deal.Status.COMPLETED)

	def test_dispute_endpoint_marks_deal_disputed(self):
		deal = Deal.objects.create(
			seller=self.seller,
			buyer=self.buyer,
			code="ZZYY1122",
			title="Tablet",
			description="Used tablet",
			amount="250000.00",
			fee="0.00",
			net_amount="250000.00",
			status=Deal.Status.IN_TRANSIT,
		)

		response = self.client.post(
			f"/api/v1/deals/{deal.id}/dispute",
			{"reason_category": "item_issue", "reason_detail": "Wrong item"},
			format="json",
			**self._auth_headers(self.buyer),
		)

		self.assertEqual(response.status_code, 201)
		deal.refresh_from_db()
		self.assertEqual(deal.status, Deal.Status.DISPUTED)
		self.assertTrue(deal.has_dispute)
		self.assertTrue(Dispute.objects.filter(deal=deal).exists())

	def test_list_filter_completed(self):
		Deal.objects.create(
			seller=self.seller,
			buyer=self.buyer,
			code="CMP00001",
			title="Completed",
			description="Done",
			amount="1000.00",
			fee="0.00",
			net_amount="1000.00",
			status=Deal.Status.COMPLETED,
		)
		Deal.objects.create(
			seller=self.seller,
			buyer=self.buyer,
			code="ACT00001",
			title="Active",
			description="Active",
			amount="1000.00",
			fee="0.00",
			net_amount="1000.00",
			status=Deal.Status.FUNDED,
		)

		response = self.client.get(self.deals_url + "?status=completed", **self._auth_headers(self.seller))

		self.assertEqual(response.status_code, 200)
		self.assertEqual(response.data["count"], 1)
		self.assertEqual(response.data["results"][0]["status"], Deal.Status.COMPLETED)
