import base64

import pytest

from servala.core.models import (
    BillingEntity,
    ComputePlan,
    ComputePlanAssignment,
    Organization,
    OrganizationMembership,
    OrganizationOrigin,
    User,
)
from servala.core.models.service import (
    CloudProvider,
    ControlPlane,
    ControlPlaneCRD,
    Service,
    ServiceCategory,
    ServiceDefinition,
    ServiceInstance,
    ServiceOffering,
)


@pytest.fixture
def origin():
    return OrganizationOrigin.objects.create(name="TESTORIGIN")


@pytest.fixture
def billing_entity():
    return BillingEntity.objects.create(name="Test Entity")


@pytest.fixture
def organization(origin):
    return Organization.objects.create(name="Test Org", origin=origin)


@pytest.fixture
def other_organization(origin):
    return Organization.objects.create(name="Test Org Alternate", origin=origin)


@pytest.fixture
def org_owner(organization):
    owner = User.objects.create(email="owner@example.org", password="example")
    OrganizationMembership.objects.create(
        organization=organization, user=owner, role="owner"
    )
    return owner


@pytest.fixture
def org_admin(organization):
    admin = User.objects.create(email="admin@example.org", password="example")
    OrganizationMembership.objects.create(
        organization=organization, user=admin, role="admin"
    )
    return admin


@pytest.fixture
def org_member(organization):
    member = User.objects.create(email="member@example.org", password="example")
    OrganizationMembership.objects.create(
        organization=organization, user=member, role="member"
    )
    return member


@pytest.fixture
def user():
    return User.objects.create(email="generic-user@example.org", password="example")


@pytest.fixture
def service_category():
    return ServiceCategory.objects.create(
        name="Databases",
        description="Database services",
    )


@pytest.fixture
def service(service_category):
    return Service.objects.create(
        name="Redis",
        slug="redis",
        category=service_category,
        description="Redis database service",
        osb_service_id="test-service-123",
    )


@pytest.fixture
def cloud_provider():
    return CloudProvider.objects.create(
        name="Exoscale",
        description="Exoscale cloud provider",
    )


@pytest.fixture
def service_offering(service, cloud_provider):
    return ServiceOffering.objects.create(
        service=service,
        provider=cloud_provider,
        description="Redis on Exoscale",
        osb_plan_id="test-plan-123",
    )


@pytest.fixture
def osb_client(client):
    credentials = base64.b64encode(b"testuser:testpass").decode("ascii")
    client.defaults = {"HTTP_AUTHORIZATION": f"Basic {credentials}"}
    return client


@pytest.fixture
def mock_odoo_success(mocker):
    """
    Mock Odoo client with successful responses for organization creation.
    Returns the mock object for further customization if needed.
    """
    mock_client = mocker.patch("servala.core.models.organization.CLIENT")

    # Default successful responses for organization creation
    mock_client.execute.side_effect = [
        123,  # company_id
        456,  # invoice_address_id
        789,  # sale_order_id
    ]
    mock_client.search_read.return_value = [{"name": "SO001"}]

    return mock_client


@pytest.fixture
def mock_odoo_failure(mocker):
    """
    Mock Odoo client that raises an exception to simulate failure.
    """
    mock_client = mocker.patch("servala.core.models.organization.CLIENT")
    mock_client.execute.side_effect = Exception("Odoo connection failed")
    return mock_client


@pytest.fixture
def control_plane(cloud_provider):
    return ControlPlane.objects.create(
        name="Geneva (CH-GVA-2)",
        description="Geneva control plane",
        cloud_provider=cloud_provider,
        api_credentials={
            "server": "https://k8s.example.com",
            "token": "test-token",
            "certificate_authority_data": "test-ca-data",
        },
    )


@pytest.fixture
def service_definition(service):
    return ServiceDefinition.objects.create(
        name="Redis Standard",
        service=service,
        api_definition={
            "group": "vshn.appcat.vshn.io",
            "version": "v1",
            "kind": "VSHNRedis",
        },
    )


@pytest.fixture
def control_plane_crd(service_offering, control_plane, service_definition):
    return ControlPlaneCRD.objects.create(
        service_offering=service_offering,
        control_plane=control_plane,
        service_definition=service_definition,
    )


@pytest.fixture
def compute_plan():
    return ComputePlan.objects.create(
        name="Medium",
        description="Medium resource plan",
        memory_requests="1Gi",
        memory_limits="2Gi",
        cpu_requests="500m",
        cpu_limits="1000m",
        is_active=True,
    )


@pytest.fixture
def compute_plan_assignment(compute_plan, control_plane_crd):
    return ComputePlanAssignment.objects.create(
        compute_plan=compute_plan,
        control_plane_crd=control_plane_crd,
        sla="besteffort",
        odoo_product_id="test-product-id",
        odoo_unit_id="test-unit-id",
        price="10.00",
        unit="hour",
        is_active=True,
    )


@pytest.fixture
def service_instance(organization, control_plane_crd):
    return ServiceInstance.objects.create(
        name="test-abc12345",
        display_name="My Test Instance",
        organization=organization,
        context=control_plane_crd,
    )


@pytest.fixture
def control_plane_with_storage(cloud_provider):
    return ControlPlane.objects.create(
        name="Storage Zone",
        description="Zone with storage billing",
        cloud_provider=cloud_provider,
        api_credentials={
            "server": "https://k8s.example.com",
            "token": "test-token",
            "certificate-authority-data": "test-ca-data",
        },
        storage_plan_odoo_product_id="storage-product-123",
        storage_plan_odoo_unit_id="storage-unit-456",
        storage_plan_price_per_gib="0.10",
    )
