defmodule WandererAppWeb.OpenApiV1Spec do
  @moduledoc """
  OpenAPI spec specifically for v1 JSON:API endpoints generated by AshJsonApi.
  """

  @behaviour OpenApiSpex.OpenApi

  alias OpenApiSpex.{OpenApi, Info, Server, Components}

  @impl OpenApiSpex.OpenApi
  def spec do
    # This is called by the modify_open_api option in the router
    # We should return the spec from WandererAppWeb.OpenApi module
    WandererAppWeb.OpenApi.spec()
  end

  defp generate_spec_manually do
    %OpenApi{
      info: %Info{
        title: "WandererApp v1 JSON:API",
        version: "1.0.0",
        description: """
        JSON:API compliant endpoints for WandererApp.

        ## Features
        - Filtering: Use `filter[attribute]=value` parameters
        - Sorting: Use `sort=attribute` or `sort=-attribute` for descending
        - Pagination: Use `page[limit]=n` and `page[offset]=n`
        - Relationships: Include related resources with `include=relationship`

        ## Authentication
        All endpoints require Bearer token authentication:
        ```
        Authorization: Bearer YOUR_API_KEY
        ```
        """
      },
      servers: [
        Server.from_endpoint(WandererAppWeb.Endpoint)
      ],
      paths: get_v1_paths(),
      components: %Components{
        schemas: get_v1_schemas(),
        securitySchemes: %{
          "bearerAuth" => %{
            "type" => "http",
            "scheme" => "bearer",
            "description" => "Map API key for authentication"
          }
        }
      },
      security: [%{"bearerAuth" => []}],
      tags: get_v1_tags()
    }
  end

  defp get_v1_tags do
    [
      %{"name" => "Access Lists", "description" => "Access control list management"},
      %{"name" => "Access List Members", "description" => "ACL member management"},
      %{"name" => "Characters", "description" => "Character management"},
      %{"name" => "Maps", "description" => "Map management"},
      %{"name" => "Map Systems", "description" => "Map system operations"},
      %{"name" => "Map Connections", "description" => "System connection management"},
      %{"name" => "Map Solar Systems", "description" => "Solar system data"},
      %{"name" => "Map System Signatures", "description" => "Wormhole signature tracking"},
      %{"name" => "Map System Structures", "description" => "Structure management"},
      %{"name" => "Map System Comments", "description" => "System comments"},
      %{"name" => "Map Character Settings", "description" => "Character map settings"},
      %{"name" => "Map User Settings", "description" => "User map preferences"},
      %{"name" => "Map Subscriptions", "description" => "Map subscription management"},
      %{"name" => "Map Access Lists", "description" => "Map-specific ACLs"},
      %{"name" => "Map States", "description" => "Map state information"},
      %{"name" => "Users", "description" => "User management"},
      %{"name" => "User Activities", "description" => "User activity tracking"},
      %{"name" => "Ship Type Info", "description" => "Ship type information"}
    ]
  end

  defp get_v1_paths do
    # Generate paths for all resources
    resources = [
      {"access_lists", "Access Lists"},
      {"access_list_members", "Access List Members"},
      {"characters", "Characters"},
      {"maps", "Maps"},
      {"map_systems", "Map Systems"},
      {"map_connections", "Map Connections"},
      {"map_solar_systems", "Map Solar Systems"},
      {"map_system_signatures", "Map System Signatures"},
      {"map_system_structures", "Map System Structures"},
      {"map_system_comments", "Map System Comments"},
      {"map_character_settings", "Map Character Settings"},
      {"map_user_settings", "Map User Settings"},
      {"map_subscriptions", "Map Subscriptions"},
      {"map_access_lists", "Map Access Lists"},
      {"map_states", "Map States"},
      {"users", "Users"},
      {"user_activities", "User Activities"},
      {"ship_type_infos", "Ship Type Info"}
    ]

    Enum.reduce(resources, %{}, fn {resource, tag}, acc ->
      base_path = "/api/v1/#{resource}"

      paths = %{
        base_path => %{
          "get" => %{
            "summary" => "List #{resource}",
            "tags" => [tag],
            "parameters" => get_standard_list_parameters(resource),
            "responses" => %{
              "200" => %{
                "description" => "List of #{resource}",
                "content" => %{
                  "application/vnd.api+json" => %{
                    "schema" => %{
                      "$ref" => "#/components/schemas/#{String.capitalize(resource)}ListResponse"
                    }
                  }
                }
              }
            }
          },
          "post" => %{
            "summary" => "Create #{String.replace(resource, "_", " ")}",
            "tags" => [tag],
            "requestBody" => %{
              "required" => true,
              "content" => %{
                "application/vnd.api+json" => %{
                  "schema" => %{
                    "$ref" => "#/components/schemas/#{String.capitalize(resource)}CreateRequest"
                  }
                }
              }
            },
            "responses" => %{
              "201" => %{"description" => "Created"}
            }
          }
        },
        "#{base_path}/{id}" => %{
          "get" => %{
            "summary" => "Get #{String.replace(resource, "_", " ")}",
            "tags" => [tag],
            "parameters" => [
              %{
                "name" => "id",
                "in" => "path",
                "required" => true,
                "schema" => %{"type" => "string"}
              }
            ],
            "responses" => %{
              "200" => %{"description" => "Resource details"}
            }
          },
          "patch" => %{
            "summary" => "Update #{String.replace(resource, "_", " ")}",
            "tags" => [tag],
            "parameters" => [
              %{
                "name" => "id",
                "in" => "path",
                "required" => true,
                "schema" => %{"type" => "string"}
              }
            ],
            "requestBody" => %{
              "required" => true,
              "content" => %{
                "application/vnd.api+json" => %{
                  "schema" => %{
                    "$ref" => "#/components/schemas/#{String.capitalize(resource)}UpdateRequest"
                  }
                }
              }
            },
            "responses" => %{
              "200" => %{"description" => "Updated"}
            }
          },
          "delete" => %{
            "summary" => "Delete #{String.replace(resource, "_", " ")}",
            "tags" => [tag],
            "parameters" => [
              %{
                "name" => "id",
                "in" => "path",
                "required" => true,
                "schema" => %{"type" => "string"}
              }
            ],
            "responses" => %{
              "204" => %{"description" => "Deleted"}
            }
          }
        }
      }

      Map.merge(acc, paths)
    end)
    |> add_custom_paths()
  end

  defp add_custom_paths(paths) do
    # Add custom action paths
    custom_paths = %{
      "/api/v1/maps/{id}/duplicate" => %{
        "post" => %{
          "summary" => "Duplicate map",
          "tags" => ["Maps"],
          "parameters" => [
            %{
              "name" => "id",
              "in" => "path",
              "required" => true,
              "schema" => %{"type" => "string"}
            }
          ],
          "responses" => %{
            "201" => %{"description" => "Map duplicated"}
          }
        }
      },
      "/api/v1/maps/{map_id}/systems_and_connections" => %{
        "get" => %{
          "summary" => "Get Map Systems and Connections",
          "description" => "Retrieve both systems and connections for a map in a single response",
          "tags" => ["Maps"],
          "parameters" => [
            %{
              "name" => "map_id",
              "in" => "path",
              "required" => true,
              "schema" => %{"type" => "string"},
              "description" => "Map ID"
            }
          ],
          "responses" => %{
            "200" => %{
              "description" => "Combined systems and connections data",
              "content" => %{
                "application/json" => %{
                  "schema" => %{
                    "type" => "object",
                    "properties" => %{
                      "systems" => %{
                        "type" => "array",
                        "items" => %{
                          "type" => "object",
                          "properties" => %{
                            "id" => %{"type" => "string"},
                            "solar_system_id" => %{"type" => "integer"},
                            "name" => %{"type" => "string"},
                            "status" => %{"type" => "string"},
                            "visible" => %{"type" => "boolean"},
                            "locked" => %{"type" => "boolean"},
                            "position_x" => %{"type" => "integer"},
                            "position_y" => %{"type" => "integer"}
                          }
                        }
                      },
                      "connections" => %{
                        "type" => "array",
                        "items" => %{
                          "type" => "object",
                          "properties" => %{
                            "id" => %{"type" => "string"},
                            "solar_system_source" => %{"type" => "integer"},
                            "solar_system_target" => %{"type" => "integer"},
                            "type" => %{"type" => "string"},
                            "time_status" => %{"type" => "string"},
                            "mass_status" => %{"type" => "string"}
                          }
                        }
                      }
                    }
                  }
                }
              }
            },
            "404" => %{"description" => "Map not found"},
            "401" => %{"description" => "Unauthorized"}
          }
        }
      }
    }

    Map.merge(paths, custom_paths)
  end

  defp get_standard_list_parameters(resource) do
    base_params = [
      %{
        "name" => "sort",
        "in" => "query",
        "description" => "Sort results (e.g., 'name', '-created_at')",
        "schema" => %{"type" => "string"}
      },
      %{
        "name" => "page[limit]",
        "in" => "query",
        "description" => "Number of results per page",
        "schema" => %{"type" => "integer", "default" => 50}
      },
      %{
        "name" => "page[offset]",
        "in" => "query",
        "description" => "Offset for pagination",
        "schema" => %{"type" => "integer", "default" => 0}
      },
      %{
        "name" => "include",
        "in" => "query",
        "description" => "Include related resources (comma-separated)",
        "schema" => %{"type" => "string"}
      }
    ]

    # Add resource-specific filter parameters
    filter_params =
      case resource do
        "characters" ->
          [
            %{
              "name" => "filter[name]",
              "in" => "query",
              "description" => "Filter by character name",
              "schema" => %{"type" => "string"}
            },
            %{
              "name" => "filter[user_id]",
              "in" => "query",
              "description" => "Filter by user ID",
              "schema" => %{"type" => "string"}
            }
          ]

        "maps" ->
          [
            %{
              "name" => "filter[scope]",
              "in" => "query",
              "description" => "Filter by map scope",
              "schema" => %{"type" => "string"}
            },
            %{
              "name" => "filter[archived]",
              "in" => "query",
              "description" => "Filter by archived status",
              "schema" => %{"type" => "boolean"}
            }
          ]

        "map_systems" ->
          [
            %{
              "name" => "filter[map_id]",
              "in" => "query",
              "description" => "Filter by map ID",
              "schema" => %{"type" => "string"}
            },
            %{
              "name" => "filter[solar_system_id]",
              "in" => "query",
              "description" => "Filter by solar system ID",
              "schema" => %{"type" => "integer"}
            }
          ]

        "map_connections" ->
          [
            %{
              "name" => "filter[map_id]",
              "in" => "query",
              "description" => "Filter by map ID",
              "schema" => %{"type" => "string"}
            },
            %{
              "name" => "filter[source_id]",
              "in" => "query",
              "description" => "Filter by source system ID",
              "schema" => %{"type" => "string"}
            },
            %{
              "name" => "filter[target_id]",
              "in" => "query",
              "description" => "Filter by target system ID",
              "schema" => %{"type" => "string"}
            }
          ]

        "map_system_signatures" ->
          [
            %{
              "name" => "filter[system_id]",
              "in" => "query",
              "description" => "Filter by system ID",
              "schema" => %{"type" => "string"}
            },
            %{
              "name" => "filter[type]",
              "in" => "query",
              "description" => "Filter by signature type",
              "schema" => %{"type" => "string"}
            }
          ]

        _ ->
          []
      end

    base_params ++ filter_params
  end

  defp get_v1_schemas do
    %{
      # Generic JSON:API response wrapper
      "JsonApiWrapper" => %{
        "type" => "object",
        "properties" => %{
          "data" => %{
            "type" => "object",
            "description" => "Primary data"
          },
          "included" => %{
            "type" => "array",
            "description" => "Included related resources"
          },
          "meta" => %{
            "type" => "object",
            "description" => "Metadata about the response"
          },
          "links" => %{
            "type" => "object",
            "description" => "Links for pagination and relationships"
          }
        }
      },
      # Character schemas
      "CharacterResource" => %{
        "type" => "object",
        "properties" => %{
          "type" => %{"type" => "string", "enum" => ["characters"]},
          "id" => %{"type" => "string"},
          "attributes" => %{
            "type" => "object",
            "properties" => %{
              "name" => %{"type" => "string"},
              "eve_id" => %{"type" => "integer"},
              "corporation_id" => %{"type" => "integer"},
              "alliance_id" => %{"type" => "integer"},
              "online" => %{"type" => "boolean"},
              "location" => %{"type" => "object"},
              "inserted_at" => %{"type" => "string", "format" => "date-time"},
              "updated_at" => %{"type" => "string", "format" => "date-time"}
            }
          },
          "relationships" => %{
            "type" => "object",
            "properties" => %{
              "user" => %{
                "type" => "object",
                "properties" => %{
                  "data" => %{
                    "type" => "object",
                    "properties" => %{
                      "type" => %{"type" => "string"},
                      "id" => %{"type" => "string"}
                    }
                  }
                }
              }
            }
          }
        }
      },
      "CharactersListResponse" => %{
        "type" => "object",
        "properties" => %{
          "data" => %{
            "type" => "array",
            "items" => %{"$ref" => "#/components/schemas/CharacterResource"}
          },
          "meta" => %{
            "type" => "object",
            "properties" => %{
              "page" => %{
                "type" => "object",
                "properties" => %{
                  "offset" => %{"type" => "integer"},
                  "limit" => %{"type" => "integer"},
                  "total" => %{"type" => "integer"}
                }
              }
            }
          }
        }
      },
      # Map schemas
      "MapResource" => %{
        "type" => "object",
        "properties" => %{
          "type" => %{"type" => "string", "enum" => ["maps"]},
          "id" => %{"type" => "string"},
          "attributes" => %{
            "type" => "object",
            "properties" => %{
              "name" => %{"type" => "string"},
              "slug" => %{"type" => "string"},
              "scope" => %{"type" => "string"},
              "public_key" => %{"type" => "string"},
              "archived" => %{"type" => "boolean"},
              "inserted_at" => %{"type" => "string", "format" => "date-time"},
              "updated_at" => %{"type" => "string", "format" => "date-time"}
            }
          },
          "relationships" => %{
            "type" => "object",
            "properties" => %{
              "owner" => %{
                "type" => "object"
              },
              "characters" => %{
                "type" => "object"
              },
              "acls" => %{
                "type" => "object"
              }
            }
          }
        }
      }
    }
  end
end
