# tests/integration/api/v1/test_marketplace_import_job_endpoints.py

import pytest


@pytest.mark.integration
@pytest.mark.api
@pytest.mark.marketplace
class TestMarketplaceImportJobAPI:
    def test_import_from_marketplace(
        self, client, auth_headers, test_vendor, test_user
    ):
        """Test marketplace import endpoint - just test job creation"""
        # Ensure user owns the vendor
        test_vendor.owner_user_id = test_user.id

        import_data = {
            "url": "https://example.com/products.csv",
            "marketplace": "TestMarket",
            "vendor_code": test_vendor.vendor_code,
        }

        response = client.post(
            "/api/v1/marketplace/import-product", headers=auth_headers, json=import_data
        )

        assert response.status_code == 200
        data = response.json()
        assert data["status"] == "pending"
        assert data["marketplace"] == "TestMarket"
        assert "job_id" in data
        assert data["vendor_code"] == test_vendor.vendor_code
        assert data["vendor_id"] == test_vendor.id

    def test_import_from_marketplace_invalid_vendor(self, client, auth_headers):
        """Test marketplace import with invalid vendor"""
        import_data = {
            "url": "https://example.com/products.csv",
            "marketplace": "TestMarket",
            "vendor_code": "NONEXISTENT",
        }

        response = client.post(
            "/api/v1/marketplace/import-product", headers=auth_headers, json=import_data
        )

        assert response.status_code == 404
        data = response.json()
        assert data["error_code"] == "VENDOR_NOT_FOUND"
        assert "NONEXISTENT" in data["message"]

    def test_import_from_marketplace_unauthorized_vendor(
        self, client, auth_headers, test_vendor, other_user
    ):
        """Test marketplace import with unauthorized vendor access"""
        # Set vendor owner to different user
        test_vendor.owner_user_id = other_user.id

        import_data = {
            "url": "https://example.com/products.csv",
            "marketplace": "TestMarket",
            "vendor_code": test_vendor.vendor_code,
        }

        response = client.post(
            "/api/v1/marketplace/import-product", headers=auth_headers, json=import_data
        )

        assert response.status_code == 403
        data = response.json()
        assert data["error_code"] == "UNAUTHORIZED_VENDOR_ACCESS"
        assert test_vendor.vendor_code in data["message"]

    def test_import_from_marketplace_validation_error(self, client, auth_headers):
        """Test marketplace import with invalid request data"""
        import_data = {
            "url": "",  # Empty URL
            "marketplace": "",  # Empty marketplace
            # Missing vendor_code
        }

        response = client.post(
            "/api/v1/marketplace/import-product", headers=auth_headers, json=import_data
        )

        assert response.status_code == 422
        data = response.json()
        assert data["error_code"] == "VALIDATION_ERROR"
        assert "Request validation failed" in data["message"]

    def test_import_from_marketplace_admin_access(
        self, client, admin_headers, test_vendor
    ):
        """Test that admin can import for any vendor"""
        import_data = {
            "url": "https://example.com/products.csv",
            "marketplace": "AdminMarket",
            "vendor_code": test_vendor.vendor_code,
        }

        response = client.post(
            "/api/v1/marketplace/import-product",
            headers=admin_headers,
            json=import_data,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["marketplace"] == "AdminMarket"
        assert data["vendor_code"] == test_vendor.vendor_code

    def test_get_marketplace_import_status(
        self, client, auth_headers, test_marketplace_import_job
    ):
        """Test getting marketplace import status"""
        response = client.get(
            f"/api/v1/marketplace/import-status/{test_marketplace_import_job.id}",
            headers=auth_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["job_id"] == test_marketplace_import_job.id
        assert data["status"] == test_marketplace_import_job.status
        assert data["marketplace"] == test_marketplace_import_job.marketplace

    def test_get_marketplace_import_status_not_found(self, client, auth_headers):
        """Test getting status of non-existent import job"""
        response = client.get(
            "/api/v1/marketplace/import-status/99999", headers=auth_headers
        )

        assert response.status_code == 404
        data = response.json()
        assert data["error_code"] == "IMPORT_JOB_NOT_FOUND"
        assert "99999" in data["message"]

    def test_get_marketplace_import_status_unauthorized(
        self, client, auth_headers, test_marketplace_import_job, other_user
    ):
        """Test getting status of unauthorized import job"""
        # Change job owner to other user
        test_marketplace_import_job.user_id = other_user.id

        response = client.get(
            f"/api/v1/marketplace/import-status/{test_marketplace_import_job.id}",
            headers=auth_headers,
        )

        assert response.status_code == 403
        data = response.json()
        assert data["error_code"] == "IMPORT_JOB_NOT_OWNED"

    def test_get_marketplace_import_jobs(
        self, client, auth_headers, test_marketplace_import_job
    ):
        """Test getting marketplace import jobs"""
        response = client.get("/api/v1/marketplace/import-jobs", headers=auth_headers)

        assert response.status_code == 200
        data = response.json()
        assert isinstance(data, list)
        assert len(data) >= 1

        # Find our test job in the results
        job_ids = [job["job_id"] for job in data]
        assert test_marketplace_import_job.id in job_ids

    def test_get_marketplace_import_jobs_with_filters(
        self, client, auth_headers, test_marketplace_import_job
    ):
        """Test getting import jobs with filters"""
        response = client.get(
            f"/api/v1/marketplace/import-jobs?marketplace={test_marketplace_import_job.marketplace}",
            headers=auth_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert isinstance(data, list)
        assert len(data) >= 1

        for job in data:
            assert (
                test_marketplace_import_job.marketplace.lower()
                in job["marketplace"].lower()
            )

    def test_get_marketplace_import_jobs_pagination(self, client, auth_headers):
        """Test import jobs pagination"""
        response = client.get(
            "/api/v1/marketplace/import-jobs?skip=0&limit=5", headers=auth_headers
        )

        assert response.status_code == 200
        data = response.json()
        assert isinstance(data, list)
        assert len(data) <= 5

    def test_get_marketplace_import_stats(
        self, client, auth_headers, test_marketplace_import_job
    ):
        """Test getting marketplace import statistics"""
        response = client.get(
            "/api/v1/marketplace/marketplace-import-stats", headers=auth_headers
        )

        assert response.status_code == 200
        data = response.json()
        assert "total_jobs" in data
        assert "pending_jobs" in data
        assert "running_jobs" in data
        assert "completed_jobs" in data
        assert "failed_jobs" in data
        assert isinstance(data["total_jobs"], int)
        assert data["total_jobs"] >= 1

    def test_cancel_marketplace_import_job(
        self, client, auth_headers, test_user, test_vendor, db
    ):
        """Test cancelling a marketplace import job"""
        # Create a pending job that can be cancelled
        import uuid

        from models.database.marketplace_import_job import MarketplaceImportJob

        unique_id = str(uuid.uuid4())[:8]
        job = MarketplaceImportJob(
            status="pending",
            marketplace="TestMarket",
            vendor_name=f"Test_vendor_{unique_id}",
            user_id=test_user.id,
            vendor_id=test_vendor.id,
            source_url="https://test.example.com/import",
            imported_count=0,
            updated_count=0,
            total_processed=0,
            error_count=0,
        )
        db.add(job)
        db.commit()
        db.refresh(job)

        response = client.put(
            f"/api/v1/marketplace/import-jobs/{job.id}/cancel", headers=auth_headers
        )

        assert response.status_code == 200
        data = response.json()
        assert data["job_id"] == job.id
        assert data["status"] == "cancelled"
        assert data["completed_at"] is not None

    def test_cancel_marketplace_import_job_not_found(self, client, auth_headers):
        """Test cancelling non-existent import job"""
        response = client.put(
            "/api/v1/marketplace/import-jobs/99999/cancel", headers=auth_headers
        )

        assert response.status_code == 404
        data = response.json()
        assert data["error_code"] == "IMPORT_JOB_NOT_FOUND"

    def test_cancel_marketplace_import_job_cannot_cancel(
        self, client, auth_headers, test_marketplace_import_job, db
    ):
        """Test cancelling a job that cannot be cancelled"""
        # Set job to completed status
        test_marketplace_import_job.status = "completed"
        db.commit()

        response = client.put(
            f"/api/v1/marketplace/import-jobs/{test_marketplace_import_job.id}/cancel",
            headers=auth_headers,
        )

        assert response.status_code == 400
        data = response.json()
        assert data["error_code"] == "IMPORT_JOB_CANNOT_BE_CANCELLED"
        assert "completed" in data["message"]

    def test_delete_marketplace_import_job(
        self, client, auth_headers, test_user, test_vendor, db
    ):
        """Test deleting a marketplace import job"""
        # Create a completed job that can be deleted
        import uuid

        from models.database.marketplace_import_job import MarketplaceImportJob

        unique_id = str(uuid.uuid4())[:8]
        job = MarketplaceImportJob(
            status="completed",
            marketplace="TestMarket",
            vendor_name=f"Test_vendor_{unique_id}",
            user_id=test_user.id,
            vendor_id=test_vendor.id,
            source_url="https://test.example.com/import",
            imported_count=0,
            updated_count=0,
            total_processed=0,
            error_count=0,
        )
        db.add(job)
        db.commit()
        db.refresh(job)

        response = client.delete(
            f"/api/v1/marketplace/import-jobs/{job.id}", headers=auth_headers
        )

        assert response.status_code == 200
        data = response.json()
        assert "deleted successfully" in data["message"]

    def test_delete_marketplace_import_job_not_found(self, client, auth_headers):
        """Test deleting non-existent import job"""
        response = client.delete(
            "/api/v1/marketplace/import-jobs/99999", headers=auth_headers
        )

        assert response.status_code == 404
        data = response.json()
        assert data["error_code"] == "IMPORT_JOB_NOT_FOUND"

    def test_delete_marketplace_import_job_cannot_delete(
        self, client, auth_headers, test_user, test_vendor, db
    ):
        """Test deleting a job that cannot be deleted"""
        # Create a pending job that cannot be deleted
        import uuid

        from models.database.marketplace_import_job import MarketplaceImportJob

        unique_id = str(uuid.uuid4())[:8]
        job = MarketplaceImportJob(
            status="pending",
            marketplace="TestMarket",
            vendor_name=f"Test_vendor_{unique_id}",
            user_id=test_user.id,
            vendor_id=test_vendor.id,
            source_url="https://test.example.com/import",
            imported_count=0,
            updated_count=0,
            total_processed=0,
            error_count=0,
        )
        db.add(job)
        db.commit()
        db.refresh(job)

        response = client.delete(
            f"/api/v1/marketplace/import-jobs/{job.id}", headers=auth_headers
        )

        assert response.status_code == 400
        data = response.json()
        assert data["error_code"] == "IMPORT_JOB_CANNOT_BE_DELETED"
        assert "pending" in data["message"]

    def test_get_marketplace_without_auth(self, client):
        """Test that marketplace endpoints require authentication"""
        response = client.get("/api/v1/marketplace/import-jobs")
        assert response.status_code == 401
        data = response.json()
        assert data["error_code"] == "INVALID_TOKEN"

    def test_import_without_auth(self, client):
        """Test marketplace import without authentication"""
        import_data = {
            "url": "https://example.com/products.csv",
            "marketplace": "TestMarket",
            "vendor_code": "TEST_VENDOR",
        }

        response = client.post("/api/v1/marketplace/import-product", json=import_data)
        assert response.status_code == 401
        data = response.json()
        assert data["error_code"] == "INVALID_TOKEN"

    def test_admin_can_access_all_jobs(
        self, client, admin_headers, test_marketplace_import_job
    ):
        """Test that admin can access all import jobs"""
        response = client.get("/api/v1/marketplace/import-jobs", headers=admin_headers)

        assert response.status_code == 200
        data = response.json()
        assert isinstance(data, list)
        # Admin should see all jobs, including the test job
        job_ids = [job["job_id"] for job in data]
        assert test_marketplace_import_job.id in job_ids

    def test_admin_can_view_any_job_status(
        self, client, admin_headers, test_marketplace_import_job
    ):
        """Test that admin can view any job status"""
        response = client.get(
            f"/api/v1/marketplace/import-status/{test_marketplace_import_job.id}",
            headers=admin_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["job_id"] == test_marketplace_import_job.id

    def test_admin_can_cancel_any_job(
        self, client, admin_headers, test_user, test_vendor, db
    ):
        """Test that admin can cancel any job"""
        # Create a pending job owned by different user
        import uuid

        from models.database.marketplace_import_job import MarketplaceImportJob

        unique_id = str(uuid.uuid4())[:8]
        job = MarketplaceImportJob(
            status="pending",
            marketplace="TestMarket",
            vendor_name=f"Test_vendor_{unique_id}",
            user_id=test_user.id,  # Different user
            vendor_id=test_vendor.id,
            source_url="https://test.example.com/import",
            imported_count=0,
            updated_count=0,
            total_processed=0,
            error_count=0,
        )
        db.add(job)
        db.commit()
        db.refresh(job)

        response = client.put(
            f"/api/v1/marketplace/import-jobs/{job.id}/cancel", headers=admin_headers
        )

        assert response.status_code == 200
        data = response.json()
        assert data["status"] == "cancelled"

    def test_rate_limiting_applied(self, client, auth_headers, test_vendor, test_user):
        """Test that rate limiting is applied to import endpoint"""
        # This test verifies that the rate_limit decorator is present
        # Actual rate limiting testing would require multiple requests
        test_vendor.owner_user_id = test_user.id

        import_data = {
            "url": "https://example.com/products.csv",
            "marketplace": "TestMarket",
            "vendor_code": test_vendor.vendor_code,
        }

        response = client.post(
            "/api/v1/marketplace/import-product", headers=auth_headers, json=import_data
        )

        # Should succeed on first request
        assert response.status_code == 200
