import pytest
from fastapi.testclient import TestClient

def test_send_otp_success(authenticated_client: TestClient, mocker):
    mocker.patch("app.routers.checkin_ftth_new.send_whatsapp_otp", return_value=True)
    mocker.patch("app.routers.checkin_ftth_new.store_otp", return_value=None)

    response = authenticated_client.post(
        "/checkin-ftth/send-otp",
        json={"nomor_pelanggan": "081234567890"}
    )
    
    assert response.status_code == 200
    assert response.json()["meta"]["success"] is True


def test_send_otp_failed(authenticated_client: TestClient, mocker):
    mocker.patch("app.routers.checkin_ftth_new.send_whatsapp_otp", return_value=False)

    response = authenticated_client.post(
        "/checkin-ftth/send-otp",
        json={"nomor_pelanggan": "081234567890"}
    )
    
    assert response.status_code == 500
    assert "Error: internal server error" in response.json()["meta"]["error"]


def test_create_pelanggan_success(authenticated_client: TestClient, mocker):
    mocker.patch("app.routers.checkin_ftth_new.verify_and_delete_otp", return_value=True)
    mocker.patch("app.routers.checkin_ftth_new.CheckinService.create_pelanggan_record", return_value={"id": "123e4567-e89b-12d3-a456-426614174000", "no_activity": "ACT-123", "nama_pelanggan": "P", "nomor_pelanggan": "08", "latitude_rumah": 0.0, "longitude_rumah": 0.0, "kode_sales": "S", "status": "pending", "tanggal": "2023-01-01T00:00:00"})

    response = authenticated_client.post(
        "/checkin-ftth/pelanggan",
        data={
            "nama_pelanggan": "Pelanggan 1",
            "nomor_pelanggan": "081234567890",
            "latitude_rumah": -6.2,
            "longitude_rumah": 106.8,
            "keterangan": "Test",
            "otp_code": "1234"
        }
    )
    
    assert response.status_code == 201
    assert response.json()["data"]["no_activity"] == "ACT-123"


def test_create_pelanggan_invalid_otp(authenticated_client: TestClient, mocker):
    mocker.patch("app.routers.checkin_ftth_new.verify_and_delete_otp", return_value=False)

    response = authenticated_client.post(
        "/checkin-ftth/pelanggan",
        data={
            "nama_pelanggan": "Pelanggan 1",
            "nomor_pelanggan": "081234567890",
            "latitude_rumah": -6.2,
            "longitude_rumah": 106.8,
            "keterangan": "Test",
            "otp_code": "9999"
        }
    )
    
    assert response.status_code == 400
    assert "OTP tidak valid" in response.json()["meta"]["error"]


def test_create_pelanggan_no_auth(client: TestClient):
    response = client.post(
        "/checkin-ftth/pelanggan",
        data={"nama_pelanggan": "A", "nomor_pelanggan": "08", "latitude_rumah": 0, "longitude_rumah": 0, "otp_code": "123"}
    )
    assert response.status_code == 401


def test_history_with_data(authenticated_client: TestClient, mocker):
    mocker.patch("app.routers.checkin_ftth_new.CheckinService.get_history_list", return_value=[
        {"id": "123e4567-e89b-12d3-a456-426614174000", "no_activity": "ACT-1", "nama_pelanggan": "P1", "tanggal": "2023-01-01T00:00:00", "form_status": "pending", "status_pemesanan": "PO", "kode_sales": "S"}
    ])

    response = authenticated_client.get("/checkin-ftth/history")
    
    assert response.status_code == 200
    assert len(response.json()["data"]) == 1


def test_history_empty(authenticated_client: TestClient, mocker):
    mocker.patch("app.routers.checkin_ftth_new.CheckinService.get_history_list", return_value=[])

    response = authenticated_client.get("/checkin-ftth/history")
    
    assert response.status_code == 200
    assert len(response.json()["data"]) == 0


def test_pending_detail_found(authenticated_client: TestClient, mocker):
    mocker.patch("app.routers.checkin_ftth_new.CheckinService.get_pending_detail", return_value={"id": "123e4567-e89b-12d3-a456-426614174000", "no_activity": "ACT-1", "nama_pelanggan": "P", "nomor_pelanggan": "08", "latitude_rumah": 0.0, "longitude_rumah": 0.0, "kode_sales": "S", "status": "pending", "tanggal": "2023-01-01T00:00:00"})

    response = authenticated_client.get("/checkin-ftth/pending/ACT-1")
    
    assert response.status_code == 200
    assert response.json()["data"]["no_activity"] == "ACT-1"


def test_pending_detail_not_found(authenticated_client: TestClient, mocker):
    mocker.patch("app.routers.checkin_ftth_new.CheckinService.get_pending_detail", side_effect=ValueError("Data pending tidak ditemukan"))

    response = authenticated_client.get("/checkin-ftth/pending/INVALID")
    
    assert response.status_code == 404


def test_submit_checkin_success(authenticated_client: TestClient, mocker):
    mocker.patch("app.routers.checkin_ftth_new.CheckinService.create_checkin_from_form2", return_value={"id": "123e4567-e89b-12d3-a456-426614174000", "no_activity": "ACT-1", "nama_pelanggan": "P", "nomor_pelanggan": "08", "latitude_rumah": 0.0, "longitude_rumah": 0.0, "fat_code": "FAT-1", "foto_fat": "A.jpg", "latitude_fat": 0.0, "longitude_fat": 0.0, "jarak_meter": 0.0, "status_pemesanan": "PO", "kode_sales": "S", "status_checkin": "done", "tanggal_form1": "2023-01-01T00:00:00", "tanggal_checkin": "2023-01-01T00:00:00"})

    response = authenticated_client.post(
        "/checkin-ftth/submit",
        data={
            "no_activity": "ACT-1",
            "fat_code": "FAT-1",
            "latitude_sales": -6.2,
            "longitude_sales": 106.8,
            "status_pemesanan": "PO"
        },
        files={"foto_fat": ("test.jpg", b"fake", "image/jpeg")}
    )
    
    assert response.status_code == 201


def test_submit_checkin_terlalu_jauh(authenticated_client: TestClient, mocker):
    mocker.patch("app.routers.checkin_ftth_new.CheckinService.create_checkin_from_form2", side_effect=ValueError("Jarak lokasi FAT (50.0m) melebihi batas toleransi"))

    response = authenticated_client.post(
        "/checkin-ftth/submit",
        data={
            "no_activity": "ACT-1",
            "fat_code": "FAT-1",
            "latitude_sales": -6.2,
            "longitude_sales": 106.8,
            "status_pemesanan": "PO"
        },
        files={"foto_fat": ("test.jpg", b"fake", "image/jpeg")}
    )
    
    assert response.status_code == 400
    assert "melebihi batas toleransi" in response.json()["meta"]["error"]


def get_mock_fat_response():
    return {
        "checkin": {"id": "123e4567-e89b-12d3-a456-426614174000", "no_activity": "ACT-1", "nama_pelanggan": "P", "nomor_pelanggan": "08", "latitude_rumah": 0.0, "longitude_rumah": 0.0, "fat_code": "FAT-1", "foto_fat": "A.jpg", "latitude_fat": 0.0, "longitude_fat": 0.0, "jarak_meter": 0.0, "status_pemesanan": "PO", "kode_sales": "S", "status_checkin": "done", "tanggal_form1": "2023-01-01T00:00:00", "tanggal_checkin": "2023-01-01T00:00:00"},
        "fat_baru": {"id": "123e4567-e89b-12d3-a456-426614174001", "fat_code": "FAT-NEW", "tipe_fat": "A", "longitude_fat": 0.0, "latitude_fat": 0.0, "slot_available": 8, "slot_occupied": 0, "date": "2023-01-01T00:00:00", "status": "active", "sales_code": "S"}
    }

def test_submit_new_fat_success(authenticated_client: TestClient, mocker):
    mocker.patch("app.routers.checkin_ftth_new.CheckinService.submit_new_fat", return_value=get_mock_fat_response())

    response = authenticated_client.post(
        "/checkin-ftth/submit-new-fat",
        data={
            "no_activity": "ACT-1",
            "tipe_fat": "A",
            "latitude_fat": -6.2,
            "longitude_fat": 106.8,
            "status_pemesanan": "PO"
        }
    )
    
    assert response.status_code == 201


def test_join_new_fat_success(authenticated_client: TestClient, mocker):
    mocker.patch("app.routers.checkin_ftth_new.CheckinService.join_new_fat", return_value=get_mock_fat_response())

    response = authenticated_client.post(
        "/checkin-ftth/join-new-fat",
        data={
            "no_activity": "ACT-1",
            "fat_code": "FAT-JOIN",
            "status_pemesanan": "PO"
        }
    )
    
    assert response.status_code == 201


def test_fat_baru_nearby_found(authenticated_client: TestClient, mocker):
    mocker.patch("app.routers.checkin_ftth_new.CheckinService.get_nearby_fat_baru", return_value=[{"id": "123e4567-e89b-12d3-a456-426614174000", "fat_code": "FAT-1", "slot_available": 8, "slot_occupied": 0, "jarak_meter": 5.0, "status": "active"}])

    response = authenticated_client.get("/checkin-ftth/fat-baru/nearby?latitude=-6.2&longitude=106.8")
    
    assert response.status_code == 200
    assert len(response.json()["data"]) == 1


def test_fat_baru_detail_success(authenticated_client: TestClient, mocker):
    mocker.patch("app.routers.checkin_ftth_new.CheckinService.get_fat_baru_detail", return_value={"id": "123e4567-e89b-12d3-a456-426614174000", "fat_code": "FAT-NEW", "tipe_fat": "A", "longitude_fat": 0.0, "latitude_fat": 0.0, "slot_available": 8, "slot_occupied": 0, "date": "2023-01-01T00:00:00", "status": "active", "sales_code": "S"})

    response = authenticated_client.get("/checkin-ftth/fat-baru/FAT-1")
    
    assert response.status_code == 200
    assert response.json()["data"]["fat_code"] == "FAT-NEW"


def test_fat_baru_detail_not_found(authenticated_client: TestClient, mocker):
    mocker.patch("app.routers.checkin_ftth_new.CheckinService.get_fat_baru_detail", side_effect=ValueError("FAT Baru tidak ditemukan"))

    response = authenticated_client.get("/checkin-ftth/fat-baru/INVALID")
    
    assert response.status_code == 404


def test_done_detail_success(authenticated_client: TestClient, mocker):
    mocker.patch("app.routers.checkin_ftth_new.CheckinService.get_done_detail", return_value={"id": "123e4567-e89b-12d3-a456-426614174000", "no_activity": "ACT-1", "nama_pelanggan": "P", "nomor_pelanggan": "08", "latitude_rumah": 0.0, "longitude_rumah": 0.0, "fat_code": "FAT-1", "foto_fat": "A.jpg", "latitude_fat": 0.0, "longitude_fat": 0.0, "jarak_meter": 0.0, "status_pemesanan": "PO", "kode_sales": "S", "status_checkin": "done", "tanggal_form1": "2023-01-01T00:00:00", "tanggal_checkin": "2023-01-01T00:00:00"})

    response = authenticated_client.get("/checkin-ftth/done/ACT-1")
    
    assert response.status_code == 200
    assert response.json()["data"]["no_activity"] == "ACT-1"


def test_done_detail_not_found(authenticated_client: TestClient, mocker):
    mocker.patch("app.routers.checkin_ftth_new.CheckinService.get_done_detail", side_effect=ValueError("Data checkin tidak ditemukan"))

    response = authenticated_client.get("/checkin-ftth/done/INVALID")
    
    assert response.status_code == 404


def test_pemesanan_success(authenticated_client: TestClient, mocker):
    mocker.patch("app.routers.checkin_ftth_new.CheckinService.get_pemesanan_status", return_value=[{"id": "123e4567-e89b-12d3-a456-426614174000", "no_activity": "ACT-1", "nama_pelanggan": "P", "tanggal_checkin": "2023-01-01T00:00:00", "status_pemesanan": "PO", "kode_sales": "S"}])

    response = authenticated_client.get("/checkin-ftth/pemesanan")
    
    assert response.status_code == 200
    assert len(response.json()["data"]) == 1


def test_pemesanan_with_filter(authenticated_client: TestClient, mocker):
    mocker.patch("app.routers.checkin_ftth_new.CheckinService.get_pemesanan_status", return_value=[])

    response = authenticated_client.get("/checkin-ftth/pemesanan?status_filter=SA")
    
    assert response.status_code == 200
    assert len(response.json()["data"]) == 0


def test_update_status_success(authenticated_client: TestClient, mocker):
    mocker.patch("app.routers.checkin_ftth_new.CheckinService.update_checkin_status", return_value={"id": "123e4567-e89b-12d3-a456-426614174000", "no_activity": "ACT-1", "nama_pelanggan": "P", "nomor_pelanggan": "08", "latitude_rumah": 0.0, "longitude_rumah": 0.0, "fat_code": "FAT-1", "foto_fat": "A.jpg", "latitude_fat": 0.0, "longitude_fat": 0.0, "jarak_meter": 0.0, "status_pemesanan": "SO", "kode_sales": "S", "status_checkin": "done", "tanggal_form1": "2023-01-01T00:00:00", "tanggal_checkin": "2023-01-01T00:00:00"})

    response = authenticated_client.put(
        "/checkin-ftth/status/ACT-1",
        json={"status_pemesanan": "SO"}
    )
    
    assert response.status_code == 200


def test_update_status_invalid_order(authenticated_client: TestClient, mocker):
    mocker.patch("app.routers.checkin_ftth_new.CheckinService.update_checkin_status", side_effect=ValueError("Status pemesanan hanya bisa berubah maju"))

    response = authenticated_client.put(
        "/checkin-ftth/status/ACT-1",
        json={"status_pemesanan": "PO"} # asumsikan current status SO
    )
    
    assert response.status_code == 400


def test_update_fat_new_success(authenticated_client: TestClient, mocker):
    mocker.patch("app.routers.checkin_ftth_new.CheckinService.update_fat_new", return_value=get_mock_fat_response())

    response = authenticated_client.put(
        "/checkin-ftth/update-fat/new/ACT-1",
        data={
            "tipe_fat": "A",
            "latitude_fat": -6.2,
            "longitude_fat": 106.8
        }
    )
    
    assert response.status_code == 200


def test_update_fat_join_success(authenticated_client: TestClient, mocker):
    mocker.patch("app.routers.checkin_ftth_new.CheckinService.update_fat_join", return_value=get_mock_fat_response())

    response = authenticated_client.put(
        "/checkin-ftth/update-fat/join/ACT-1",
        data={"fat_code": "FAT-1"}
    )
    
    assert response.status_code == 200
