# frozen_string_literal: true

require 'swagger_helper'

describe 'Visits API', type: :request do
  let(:user) { create(:user) }
  let(:api_key) { user.api_key }
  let(:place) { create(:place) }
  let(:test_visit) { create(:visit, user: user, place: place) }

  path '/api/v1/visits' do
    get 'List visits' do
      tags 'Visits'
      produces 'application/json'
      parameter name: :Authorization, in: :header, type: :string, required: true, description: 'Bearer token'
      parameter name: :start_at, in: :query, type: :string, required: false, description: 'Start date (ISO 8601)'
      parameter name: :end_at, in: :query, type: :string, required: false, description: 'End date (ISO 8601)'
      parameter name: :selection, in: :query, type: :string, required: false, description: 'Set to "true" for area-based search'
      parameter name: :sw_lat, in: :query, type: :number, required: false, description: 'Southwest latitude for area search'
      parameter name: :sw_lng, in: :query, type: :number, required: false, description: 'Southwest longitude for area search'
      parameter name: :ne_lat, in: :query, type: :number, required: false, description: 'Northeast latitude for area search'
      parameter name: :ne_lng, in: :query, type: :number, required: false, description: 'Northeast longitude for area search'

      response '200', 'visits found' do
        let(:Authorization) { "Bearer #{api_key}" }
        let(:start_at) { 1.week.ago.iso8601 }
        let(:end_at) { Time.current.iso8601 }

        schema type: :array,
               items: {
                 type: :object,
                 properties: {
                   id: { type: :integer },
                   name: { type: :string },
                   status: { type: :string, enum: %w[suggested confirmed declined] },
                   started_at: { type: :string, format: :datetime },
                   ended_at: { type: :string, format: :datetime },
                   duration: { type: :integer, description: 'Duration in minutes' },
                   place: {
                     type: :object,
                     properties: {
                       id: { type: :integer },
                       name: { type: :string },
                       latitude: { type: :number },
                       longitude: { type: :number },
                       city: { type: :string },
                       country: { type: :string }
                     }
                   }
                 },
                 required: %w[id name status started_at ended_at duration]
               }

        run_test!
      end

      response '401', 'unauthorized' do
        let(:Authorization) { 'Bearer invalid-token' }
        run_test!
      end
    end

    post 'Create visit' do
      tags 'Visits'
      consumes 'application/json'
      produces 'application/json'
      parameter name: :Authorization, in: :header, type: :string, required: true, description: 'Bearer token'
      parameter name: :visit, in: :body, schema: {
        type: :object,
        properties: {
          visit: {
            type: :object,
            properties: {
              name: { type: :string },
              latitude: { type: :number },
              longitude: { type: :number },
              started_at: { type: :string, format: :datetime },
              ended_at: { type: :string, format: :datetime }
            },
            required: %w[name latitude longitude started_at ended_at]
          }
        }
      }

      response '200', 'visit created' do
        let(:Authorization) { "Bearer #{api_key}" }
        let(:visit) do
          {
            visit: {
              name: 'Test Visit',
              latitude: 52.52,
              longitude: 13.405,
              started_at: '2023-12-01T10:00:00Z',
              ended_at: '2023-12-01T12:00:00Z'
            }
          }
        end

        schema type: :object,
               properties: {
                 id: { type: :integer },
                 name: { type: :string },
                 status: { type: :string },
                 started_at: { type: :string, format: :datetime },
                 ended_at: { type: :string, format: :datetime },
                 duration: { type: :integer },
                 place: {
                   type: :object,
                   properties: {
                     id: { type: :integer },
                     name: { type: :string },
                     latitude: { type: :number },
                     longitude: { type: :number }
                   }
                 }
               }

        run_test!
      end

      response '422', 'invalid request' do
        let(:Authorization) { "Bearer #{api_key}" }
        let(:visit) do
          {
            visit: {
              name: '',
              latitude: 52.52,
              longitude: 13.405,
              started_at: '2023-12-01T10:00:00Z',
              ended_at: '2023-12-01T12:00:00Z'
            }
          }
        end

        run_test!
      end

      response '401', 'unauthorized' do
        let(:Authorization) { 'Bearer invalid-token' }
        let(:visit) do
          {
            visit: {
              name: 'Test Visit',
              latitude: 52.52,
              longitude: 13.405,
              started_at: '2023-12-01T10:00:00Z',
              ended_at: '2023-12-01T12:00:00Z'
            }
          }
        end

        run_test!
      end
    end
  end

  path '/api/v1/visits/{id}' do
    patch 'Update visit' do
      tags 'Visits'
      consumes 'application/json'
      produces 'application/json'
      parameter name: :id, in: :path, type: :integer, required: true, description: 'Visit ID'
      parameter name: :Authorization, in: :header, type: :string, required: true, description: 'Bearer token'
      parameter name: :visit, in: :body, schema: {
        type: :object,
        properties: {
          visit: {
            type: :object,
            properties: {
              name: { type: :string },
              place_id: { type: :integer },
              status: { type: :string, enum: %w[suggested confirmed declined] }
            }
          }
        }
      }

      response '200', 'visit updated' do
        let(:Authorization) { "Bearer #{api_key}" }
        let(:id) { test_visit.id }
        let(:visit) { { visit: { name: 'Updated Visit' } } }

        schema type: :object,
               properties: {
                 id: { type: :integer },
                 name: { type: :string },
                 status: { type: :string },
                 started_at: { type: :string, format: :datetime },
                 ended_at: { type: :string, format: :datetime },
                 duration: { type: :integer },
                 place: { type: :object }
               }

        run_test!
      end

      response '404', 'visit not found' do
        let(:Authorization) { "Bearer #{api_key}" }
        let(:id) { 999999 }
        let(:visit) { { visit: { name: 'Updated Visit' } } }

        run_test!
      end

      response '401', 'unauthorized' do
        let(:Authorization) { 'Bearer invalid-token' }
        let(:id) { test_visit.id }
        let(:visit) { { visit: { name: 'Updated Visit' } } }

        run_test!
      end
    end

    delete 'Delete visit' do
      tags 'Visits'
      parameter name: :id, in: :path, type: :integer, required: true, description: 'Visit ID'
      parameter name: :Authorization, in: :header, type: :string, required: true, description: 'Bearer token'

      response '204', 'visit deleted' do
        let(:Authorization) { "Bearer #{api_key}" }
        let(:id) { test_visit.id }

        run_test!
      end

      response '404', 'visit not found' do
        let(:Authorization) { "Bearer #{api_key}" }
        let(:id) { 999999 }

        run_test!
      end

      response '401', 'unauthorized' do
        let(:Authorization) { 'Bearer invalid-token' }
        let(:id) { test_visit.id }

        run_test!
      end
    end
  end

  path '/api/v1/visits/{id}/possible_places' do
    get 'Get possible places for visit' do
      tags 'Visits'
      produces 'application/json'
      parameter name: :id, in: :path, type: :integer, required: true, description: 'Visit ID'
      parameter name: :Authorization, in: :header, type: :string, required: true, description: 'Bearer token'

      response '200', 'possible places found' do
        let(:Authorization) { "Bearer #{api_key}" }
        let(:id) { test_visit.id }

        schema type: :array,
               items: {
                 type: :object,
                 properties: {
                   id: { type: :integer },
                   name: { type: :string },
                   latitude: { type: :number },
                   longitude: { type: :number },
                   city: { type: :string },
                   country: { type: :string }
                 }
               }

        run_test!
      end

      response '404', 'visit not found' do
        let(:Authorization) { "Bearer #{api_key}" }
        let(:id) { 999999 }

        run_test!
      end

      response '401', 'unauthorized' do
        let(:Authorization) { 'Bearer invalid-token' }
        let(:id) { test_visit.id }

        run_test!
      end
    end
  end

  path '/api/v1/visits/merge' do
    post 'Merge visits' do
      tags 'Visits'
      consumes 'application/json'
      produces 'application/json'
      parameter name: :Authorization, in: :header, type: :string, required: true, description: 'Bearer token'
      parameter name: :merge_params, in: :body, schema: {
        type: :object,
        properties: {
          visit_ids: {
            type: :array,
            items: { type: :integer },
            minItems: 2,
            description: 'Array of visit IDs to merge (minimum 2)'
          }
        },
        required: %w[visit_ids]
      }

      response '200', 'visits merged' do
        let(:Authorization) { "Bearer #{api_key}" }
        let(:visit1) { create(:visit, user: user) }
        let(:visit2) { create(:visit, user: user) }
        let(:merge_params) { { visit_ids: [visit1.id, visit2.id] } }

        schema type: :object,
               properties: {
                 id: { type: :integer },
                 name: { type: :string },
                 status: { type: :string },
                 started_at: { type: :string, format: :datetime },
                 ended_at: { type: :string, format: :datetime },
                 duration: { type: :integer },
                 place: { type: :object }
               }

        run_test!
      end

      response '422', 'invalid request' do
        let(:Authorization) { "Bearer #{api_key}" }
        let(:merge_params) { { visit_ids: [test_visit.id] } }

        run_test!
      end

      response '401', 'unauthorized' do
        let(:Authorization) { 'Bearer invalid-token' }
        let(:merge_params) { { visit_ids: [test_visit.id] } }

        run_test!
      end
    end
  end

  path '/api/v1/visits/bulk_update' do
    post 'Bulk update visits' do
      tags 'Visits'
      consumes 'application/json'
      produces 'application/json'
      parameter name: :Authorization, in: :header, type: :string, required: true, description: 'Bearer token'
      parameter name: :bulk_params, in: :body, schema: {
        type: :object,
        properties: {
          visit_ids: {
            type: :array,
            items: { type: :integer },
            description: 'Array of visit IDs to update'
          },
          status: {
            type: :string,
            enum: %w[suggested confirmed declined],
            description: 'New status for the visits'
          }
        },
        required: %w[visit_ids status]
      }

      response '200', 'visits updated' do
        let(:Authorization) { "Bearer #{api_key}" }
        let(:visit1) { create(:visit, user: user, status: 'suggested') }
        let(:visit2) { create(:visit, user: user, status: 'suggested') }
        let(:bulk_params) { { visit_ids: [visit1.id, visit2.id], status: 'confirmed' } }

        schema type: :object,
               properties: {
                 message: { type: :string },
                 updated_count: { type: :integer }
               }

        run_test!
      end

      response '422', 'invalid request' do
        let(:Authorization) { "Bearer #{api_key}" }
        let(:bulk_params) { { visit_ids: [test_visit.id], status: 'invalid_status' } }

        run_test!
      end

      response '401', 'unauthorized' do
        let(:Authorization) { 'Bearer invalid-token' }
        let(:bulk_params) { { visit_ids: [test_visit.id], status: 'confirmed' } }

        run_test!
      end
    end
  end
end