import json
from pathlib import Path


BASE_DIR = Path(__file__).resolve().parents[1]
MOCK_DIR = BASE_DIR / "json" / "mock_data"


def queue_response(message, task_id, status_url, **extra):
    data = {
        "task_id": task_id,
        "status_url": status_url,
    }
    data.update(extra)
    return {
        "code": 202,
        "msg": message,
        "data": data,
    }


def ok_response(data, message="success", code=200):
    return {
        "code": code,
        "msg": message,
        "data": data,
    }


def error_response(code, message, data=None):
    return {
        "code": code,
        "msg": message,
        "data": data,
    }


def task_pending(task_id):
    return ok_response(
        {
            "task_id": task_id,
            "status": "PENDING",
            "message": "تسک در صف یا یافت نشد.",
        }
    )


def task_progress(task_id, progress):
    return ok_response(
        {
            "task_id": task_id,
            "status": "PROGRESS",
            "progress": progress,
        }
    )


def task_success(task_id, result):
    return ok_response(
        {
            "task_id": task_id,
            "status": "SUCCESS",
            "result": result,
        }
    )


def task_failure(task_id, error):
    return ok_response(
        {
            "task_id": task_id,
            "status": "FAILURE",
            "error": error,
        }
    )


PLANT = {
    "id": 1,
    "name": "گوجه‌فرنگی",
    "light": "آفتاب کامل",
    "watering": "منظم، هفته‌ای ۲ تا ۳ بار",
    "soil": "لومی، غنی از مواد آلی",
    "temperature": "۲۰ تا ۳۰ درجه سانتی‌گراد",
    "planting_season": "بهار",
    "harvest_time": "۷۰ تا ۹۰ روز پس از کاشت",
    "spacing": "۴۵ تا ۶۰ سانتی‌متر",
    "fertilizer": "کود NPK متعادل",
    "created_at": "2025-03-20T10:00:00Z",
    "updated_at": "2025-03-24T10:00:00Z",
}

IRRIGATION_METHOD = {
    "id": 1,
    "name": "آبیاری قطره‌ای",
    "category": "موضعی",
    "description": "آبیاری با دبی کم و راندمان بالا",
    "water_efficiency_percent": 90.0,
    "water_pressure_required": "۱-۲ اتمسفر",
    "flow_rate": "۲-۸ لیتر در ساعت",
    "coverage_area": "بسته به طراحی سیستم",
    "soil_type": "اکثر خاک‌ها",
    "climate_suitability": "گرم و خشک",
    "created_at": "2025-03-20T10:00:00Z",
    "updated_at": "2025-03-24T10:00:00Z",
}

SOIL_DEPTHS = [
    {
        "depth_label": "0-5cm",
        "bdod": 1.31,
        "cec": 18.4,
        "cfvo": 2.0,
        "clay": 24.0,
        "nitrogen": 0.18,
        "ocd": 32.0,
        "ocs": 4.1,
        "phh2o": 7.2,
        "sand": 34.0,
        "silt": 42.0,
        "soc": 1.6,
        "wv0010": 0.31,
        "wv0033": 0.22,
        "wv1500": 0.11,
    },
    {
        "depth_label": "5-15cm",
        "bdod": 1.35,
        "cec": 17.2,
        "cfvo": 2.3,
        "clay": 26.0,
        "nitrogen": 0.16,
        "ocd": 28.0,
        "ocs": 3.7,
        "phh2o": 7.1,
        "sand": 36.0,
        "silt": 38.0,
        "soc": 1.4,
        "wv0010": 0.29,
        "wv0033": 0.2,
        "wv1500": 0.1,
    },
    {
        "depth_label": "15-30cm",
        "bdod": 1.39,
        "cec": 15.8,
        "cfvo": 2.8,
        "clay": 28.0,
        "nitrogen": 0.13,
        "ocd": 22.0,
        "ocs": 3.2,
        "phh2o": 7.0,
        "sand": 38.0,
        "silt": 34.0,
        "soc": 1.1,
        "wv0010": 0.26,
        "wv0033": 0.18,
        "wv1500": 0.09,
    },
]

SOIL_LOCATION = {
    "source": "database",
    "id": 12,
    "lon": "51.389000",
    "lat": "35.689200",
    "depths": SOIL_DEPTHS,
}

SOIL_TASK_DATA = {
    "source": "task",
    "task_id": "soil-task-123",
    "lon": 51.389,
    "lat": 35.6892,
    "status_url": "/api/soil-data/tasks/soil-task-123/status/",
}

SENSOR_DATA = {
    "farm_uuid": "550e8400-e29b-41d4-a716-446655440000",
    "center_location_id": 12,
    "weather_forecast_id": 21,
    "sensor_payload": {
        "sensor-7-1": {
            "soil_moisture": 45.2,
            "soil_temperature": 22.5,
            "soil_ph": 6.8,
            "electrical_conductivity": 1.2,
            "nitrogen": 30.0,
            "phosphorus": 15.0,
            "potassium": 20.0,
        }
    },
    "plant_ids": [1],
    "created_at": "2025-03-20T10:00:00Z",
    "updated_at": "2025-03-24T10:00:00Z",
}

SENSOR_PARAMETER = {
    "id": 3,
    "sensor_key": "sensor-7-1",
    "code": "soil_moisture",
    "name_fa": "رطوبت خاک",
    "unit": "%",
    "data_type": "float",
    "metadata": {"min": 0, "max": 100},
    "created_at": "2025-03-24T10:00:00Z",
    "action": "added",
}

IRRIGATION_RECOMMENDATION_RESULT = {
    "plan": {
        "frequencyPerWeek": 3,
        "durationMinutes": 42,
        "bestTimeOfDay": "صبح زود",
        "moistureLevel": 68,
        "warning": "در صورت بارش موثر، نوبت سوم این هفته را حذف کنید.",
    },
    "raw_response": "{\"plan\":{\"frequencyPerWeek\":3,\"durationMinutes\":42}}",
    "water_balance": {
        "daily": [
            {
                "forecast_date": "2025-03-25",
                "et0_mm": 4.7,
                "etc_mm": 5.6,
                "effective_rainfall_mm": 0.0,
                "gross_irrigation_mm": 6.2,
                "irrigation_timing": "06:00-08:00",
            }
        ],
        "crop_profile": {
            "kc_initial": 0.6,
            "kc_mid": 1.15,
            "kc_end": 0.8,
        },
        "active_kc": 1.15,
    },
    "status": "completed",
}

FERTILIZATION_RECOMMENDATION_RESULT = {
    "plan": {
        "npkRatio": "20-20-20",
        "amountPerHectare": "150 kg/ha",
        "applicationMethod": "کودآبیاری در دو نوبت",
        "applicationInterval": "هر ۱۰ روز",
        "reasoning": "نیتروژن و پتاسیم خاک در محدوده متوسط است و گیاه در فاز رویشی نیاز تغذیه‌ای بالاتری دارد.",
    },
    "raw_response": "{\"plan\":{\"npkRatio\":\"20-20-20\"}}",
    "status": "completed",
}

DASHBOARD_RESULT = {
    "sensor_id": "550e8400-e29b-41d4-a716-446655440000",
    "all_cards": {
        "farmOverviewKpis": {
            "healthScore": 82,
            "activeAlerts": 2,
            "waterNeedMm": 18.4,
        },
    },
}

TASK_PROGRESS = {"current": 1, "total": 3, "message": "در حال پردازش..."}

RAG_STREAM_SUCCESS = {
    "content_type": "text/plain; charset=utf-8",
    "body": "سلام، برای بازیابی رطوبت خاک بهتر است آبیاری صبح‌گاهی را تنظیم کنید.",
}

index = []


def register(path, method, api_path, status_code, description, payload):
    full_path = MOCK_DIR / path
    full_path.parent.mkdir(parents=True, exist_ok=True)
    full_path.write_text(
        json.dumps(payload, ensure_ascii=False, indent=2) + "\n",
        encoding="utf-8",
    )
    index.append(
        {
            "method": method,
            "path": api_path,
            "status_code": status_code,
            "description": description,
            "file": str(Path("json/mock_data") / path),
        }
    )


def main():
    register(
        "dashboard-data/generate/post_202.json",
        "POST",
        "/api/dashboard-data/generate/",
        202,
        "Dashboard data task queued",
        queue_response(
            "dashboard task queued",
            "dashboard-task-123",
            "/api/dashboard-data/dashboard-task-123/status/",
        ),
    )
    register(
        "dashboard-data/generate/post_400.json",
        "POST",
        "/api/dashboard-data/generate/",
        400,
        "Missing sensor_id",
        error_response(400, "پارامتر sensor_id الزامی است.", None),
    )
    register(
        "dashboard-data/status/get_200_pending.json",
        "GET",
        "/api/dashboard-data/{task_id}/status/",
        200,
        "Pending dashboard task",
        task_pending("dashboard-task-123"),
    )
    register(
        "dashboard-data/status/get_200_progress.json",
        "GET",
        "/api/dashboard-data/{task_id}/status/",
        200,
        "Dashboard task in progress",
        task_progress(
            "dashboard-task-123",
            {"current": 5, "total": 15, "card": "sensorComparisonChart", "message": "processing sensorComparisonChart"},
        ),
    )
    register(
        "dashboard-data/status/get_200_success.json",
        "GET",
        "/api/dashboard-data/{task_id}/status/",
        200,
        "Successful dashboard task",
        task_success("dashboard-task-123", DASHBOARD_RESULT),
    )
    register(
        "dashboard-data/status/get_200_failure.json",
        "GET",
        "/api/dashboard-data/{task_id}/status/",
        200,
        "Failed dashboard task",
        task_failure("dashboard-task-123", "خطا در ساخت کارت‌های داشبورد."),
    )

    register(
        "fertilization/recommend/post_202.json",
        "POST",
        "/api/fertilization/recommend/",
        202,
        "Fertilization task queued",
        queue_response(
            "تسک توصیه کودهی در صف قرار گرفت.",
            "fert-task-123",
            "/api/fertilization/recommend/fert-task-123/status/",
        ),
    )
    register(
        "fertilization/recommend/post_400.json",
        "POST",
        "/api/fertilization/recommend/",
        400,
        "Validation error",
        error_response(400, "داده نامعتبر.", {"sensor_uuid": ["This field is required."]}),
    )
    for name, payload in {
        "pending": task_pending("fert-task-123"),
        "progress": task_progress("fert-task-123", {"message": "در حال پردازش توصیه کودهی..."}),
        "success": task_success("fert-task-123", FERTILIZATION_RECOMMENDATION_RESULT),
        "failure": task_failure("fert-task-123", "خطا در دریافت توصیه کودهی."),
    }.items():
        register(
            f"fertilization/status/get_200_{name}.json",
            "GET",
            "/api/fertilization/recommend/{task_id}/status/",
            200,
            f"Fertilization status {name}",
            payload,
        )

    register(
        "irrigation/methods/get_200.json",
        "GET",
        "/api/irrigation/",
        200,
        "List irrigation methods",
        ok_response([IRRIGATION_METHOD]),
    )
    register(
        "irrigation/methods/post_201.json",
        "POST",
        "/api/irrigation/",
        201,
        "Create irrigation method",
        ok_response(IRRIGATION_METHOD, code=201),
    )
    register(
        "irrigation/methods/post_400.json",
        "POST",
        "/api/irrigation/",
        400,
        "Irrigation create validation error",
        error_response(400, "داده نامعتبر.", {"name": ["This field is required."]}),
    )
    register(
        "irrigation/recommend/post_202.json",
        "POST",
        "/api/irrigation/recommend/",
        202,
        "Irrigation recommendation task queued",
        queue_response(
            "تسک توصیه آبیاری در صف قرار گرفت.",
            "irr-task-123",
            "/api/irrigation/recommend/irr-task-123/status/",
        ),
    )
    register(
        "irrigation/recommend/post_400.json",
        "POST",
        "/api/irrigation/recommend/",
        400,
        "Irrigation recommendation validation error",
        error_response(400, "داده نامعتبر.", {"sensor_uuid": ["This field is required."]}),
    )
    for name, payload in {
        "pending": task_pending("irr-task-123"),
        "progress": task_progress("irr-task-123", {"message": "در حال پردازش توصیه آبیاری..."}),
        "success": task_success("irr-task-123", IRRIGATION_RECOMMENDATION_RESULT),
        "failure": task_failure("irr-task-123", "خطا در دریافت توصیه آبیاری."),
    }.items():
        register(
            f"irrigation/recommend/status/get_200_{name}.json",
            "GET",
            "/api/irrigation/recommend/{task_id}/status/",
            200,
            f"Irrigation recommendation status {name}",
            payload,
        )

    for method, success_code in (("get", 200), ("put", 200), ("patch", 200)):
        register(
            f"irrigation/method-detail/{method}_{success_code}.json",
            method.upper(),
            "/api/irrigation/{pk}/",
            success_code,
            f"Irrigation method {method} success",
            ok_response(IRRIGATION_METHOD, code=success_code),
        )
        if method in {"put", "patch"}:
            register(
                f"irrigation/method-detail/{method}_400.json",
                method.upper(),
                "/api/irrigation/{pk}/",
                400,
                f"Irrigation method {method} validation error",
                error_response(400, "داده نامعتبر.", {"name": ["This field may not be blank."]}),
            )
        register(
            f"irrigation/method-detail/{method}_404.json",
            method.upper(),
            "/api/irrigation/{pk}/",
            404,
            f"Irrigation method {method} not found",
            error_response(404, "روش آبیاری یافت نشد.", None),
        )
    register(
        "irrigation/method-detail/delete_200.json",
        "DELETE",
        "/api/irrigation/{pk}/",
        200,
        "Delete irrigation method",
        error_response(200, "روش آبیاری با موفقیت حذف شد.", None),
    )
    register(
        "irrigation/method-detail/delete_404.json",
        "DELETE",
        "/api/irrigation/{pk}/",
        404,
        "Delete irrigation method not found",
        error_response(404, "روش آبیاری یافت نشد.", None),
    )

    register(
        "soil-data/get_200_database.json",
        "GET",
        "/api/soil-data/",
        200,
        "Soil data served from database",
        ok_response(SOIL_LOCATION),
    )
    register(
        "soil-data/get_202_queued.json",
        "GET",
        "/api/soil-data/",
        202,
        "Soil data fetch task queued",
        {
            "code": 202,
            "msg": "تسک در صف. وضعیت را با task_id بررسی کنید.",
            "data": SOIL_TASK_DATA,
        },
    )
    register(
        "soil-data/get_400.json",
        "GET",
        "/api/soil-data/",
        400,
        "Soil data validation error",
        error_response(400, "داده نامعتبر.", {"lat": ["This field is required."], "lon": ["This field is required."]}),
    )
    register(
        "soil-data/post_200_database.json",
        "POST",
        "/api/soil-data/",
        200,
        "Soil data POST served from database",
        ok_response(SOIL_LOCATION),
    )
    register(
        "soil-data/post_202_queued.json",
        "POST",
        "/api/soil-data/",
        202,
        "Soil data POST task queued",
        {
            "code": 202,
            "msg": "تسک در صف. وضعیت را با task_id بررسی کنید.",
            "data": SOIL_TASK_DATA,
        },
    )
    register(
        "soil-data/post_400.json",
        "POST",
        "/api/soil-data/",
        400,
        "Soil data POST validation error",
        error_response(400, "داده نامعتبر.", {"lat": ["A valid number is required."]}),
    )
    for name, payload in {
        "pending": task_pending("soil-task-123"),
        "progress": task_progress("soil-task-123", {"step": "fetch", "percent": 60}),
        "success": task_success("soil-task-123", SOIL_LOCATION | {"source": "database"}),
        "failure": task_failure("soil-task-123", "خطا در واکشی داده خاک."),
    }.items():
        register(
            f"soil-data/status/get_200_{name}.json",
            "GET",
            "/api/soil-data/tasks/{task_id}/status/",
            200,
            f"Soil task status {name}",
            payload,
        )

    register(
        "plant/list-get_200.json",
        "GET",
        "/api/plants/",
        200,
        "List plants",
        ok_response([PLANT]),
    )
    register(
        "plant/create-post_201.json",
        "POST",
        "/api/plants/",
        201,
        "Create plant",
        ok_response(PLANT, code=201),
    )
    register(
        "plant/create-post_400.json",
        "POST",
        "/api/plants/",
        400,
        "Plant create validation error",
        error_response(400, "داده نامعتبر.", {"name": ["This field is required."]}),
    )
    for method in ("get", "put", "patch"):
        register(
            f"plant/detail-{method}_200.json",
            method.upper(),
            "/api/plants/{pk}/",
            200,
            f"Plant detail {method} success",
            ok_response(PLANT),
        )
        if method in {"put", "patch"}:
            register(
                f"plant/detail-{method}_400.json",
                method.upper(),
                "/api/plants/{pk}/",
                400,
                f"Plant detail {method} validation error",
                error_response(400, "داده نامعتبر.", {"name": ["This field may not be blank."]}),
            )
        register(
            f"plant/detail-{method}_404.json",
            method.upper(),
            "/api/plants/{pk}/",
            404,
            f"Plant detail {method} not found",
            error_response(404, "گیاه یافت نشد.", None),
        )
    register(
        "plant/detail-delete_200.json",
        "DELETE",
        "/api/plants/{pk}/",
        200,
        "Delete plant success",
        error_response(200, "گیاه با موفقیت حذف شد.", None),
    )
    register(
        "plant/detail-delete_404.json",
        "DELETE",
        "/api/plants/{pk}/",
        404,
        "Delete plant not found",
        error_response(404, "گیاه یافت نشد.", None),
    )
    register(
        "plant/fetch-info-post_200.json",
        "POST",
        "/api/plants/fetch-info/",
        200,
        "Fetch plant info success",
        ok_response(PLANT),
    )
    register(
        "plant/fetch-info-post_400.json",
        "POST",
        "/api/plants/fetch-info/",
        400,
        "Fetch plant info missing name",
        error_response(400, "نام گیاه الزامی است.", None),
    )
    register(
        "plant/fetch-info-post_503.json",
        "POST",
        "/api/plants/fetch-info/",
        503,
        "Fetch plant info service unavailable",
        error_response(503, "سرویس API هنوز پیاده‌سازی نشده است.", None),
    )

    register(
        "rag/chat-post_200_stream.json",
        "POST",
        "/api/rag/chat/",
        200,
        "RAG chat streaming response",
        RAG_STREAM_SUCCESS,
    )
    register(
        "rag/chat-post_400_missing_query.json",
        "POST",
        "/api/rag/chat/",
        400,
        "Missing query",
        {"code": 400, "msg": "پارامتر query الزامی است."},
    )
    register(
        "rag/chat-post_400_invalid_service.json",
        "POST",
        "/api/rag/chat/",
        400,
        "Invalid service id",
        {"code": 400, "msg": "service_id نامعتبر است: unknown_service"},
    )
    register(
        "rag/chat-post_400_missing_user.json",
        "POST",
        "/api/rag/chat/",
        400,
        "Missing user_id for service",
        {"code": 400, "msg": "برای این service_id، پارامتر user_id الزامی است."},
    )

    register(
        "rag/irrigation/post_202.json",
        "POST",
        "/api/rag/recommend/irrigation/",
        202,
        "RAG irrigation task queued",
        queue_response(
            "تسک توصیه آبیاری در صف قرار گرفت.",
            "rag-irr-123",
            "/api/rag/recommend/irrigation/rag-irr-123/status/",
        ),
    )
    register(
        "rag/irrigation/post_400.json",
        "POST",
        "/api/rag/recommend/irrigation/",
        400,
        "RAG irrigation validation error",
        error_response(400, "پارامتر sensor_uuid الزامی است.", None),
    )
    for name, payload in {
        "pending": task_pending("rag-irr-123"),
        "progress": task_progress("rag-irr-123", {"message": "در حال پردازش توصیه آبیاری..."}),
        "success": task_success("rag-irr-123", IRRIGATION_RECOMMENDATION_RESULT),
        "failure": task_failure("rag-irr-123", "خطا در دریافت توصیه آبیاری."),
    }.items():
        register(
            f"rag/irrigation/status/get_200_{name}.json",
            "GET",
            "/api/rag/recommend/irrigation/{task_id}/status/",
            200,
            f"RAG irrigation status {name}",
            payload,
        )

    register(
        "rag/fertilization/post_202.json",
        "POST",
        "/api/rag/recommend/fertilization/",
        202,
        "RAG fertilization task queued",
        queue_response(
            "تسک توصیه کودهی در صف قرار گرفت.",
            "rag-fert-123",
            "/api/rag/recommend/fertilization/rag-fert-123/status/",
        ),
    )
    register(
        "rag/fertilization/post_400.json",
        "POST",
        "/api/rag/recommend/fertilization/",
        400,
        "RAG fertilization validation error",
        error_response(400, "پارامتر sensor_uuid الزامی است.", None),
    )
    for name, payload in {
        "pending": task_pending("rag-fert-123"),
        "progress": task_progress("rag-fert-123", {"message": "در حال پردازش توصیه کودهی..."}),
        "success": task_success("rag-fert-123", FERTILIZATION_RECOMMENDATION_RESULT),
        "failure": task_failure("rag-fert-123", "خطا در دریافت توصیه کودهی."),
    }.items():
        register(
            f"rag/fertilization/status/get_200_{name}.json",
            "GET",
            "/api/rag/recommend/fertilization/{task_id}/status/",
            200,
            f"RAG fertilization status {name}",
            payload,
        )

    register(
        "farm-data/upsert-post_201.json",
        "POST",
        "/api/farm-data/",
        201,
        "Farm data created",
        ok_response(SENSOR_DATA, code=201),
    )
    register(
        "farm-data/upsert-post_400.json",
        "POST",
        "/api/farm-data/",
        400,
        "Farm data validation error",
        error_response(400, "داده نامعتبر.", {"farm_uuid": ["This field is required."]}),
    )
    register(
        "farm-data/upsert-post_404.json",
        "POST",
        "/api/farm-data/",
        400,
        "Farm data invalid boundary",
        error_response(400, "داده نامعتبر.", {"farm_boundary": ["farm_boundary باید حداقل 3 گوشه معتبر داشته باشد."]}),
    )
    register(
        "farm-data/parameters-post_201.json",
        "POST",
        "/api/farm-data/parameters/",
        201,
        "Create sensor parameter",
        ok_response(SENSOR_PARAMETER, code=201),
    )
    register(
        "farm-data/parameters-post_400.json",
        "POST",
        "/api/farm-data/parameters/",
        400,
        "Sensor parameter validation error",
        error_response(400, "داده نامعتبر.", {"code": ["This field is required."]}),
    )

    (MOCK_DIR / "index.json").write_text(
        json.dumps(index, ensure_ascii=False, indent=2) + "\n",
        encoding="utf-8",
    )


if __name__ == "__main__":
    main()
