require "rails_helper"


RSpec.describe "Users", type: :request do
  describe "POST /users" do
    it "creates guest user and returns code" do
      post "/users"
      expect(response).to have_http_status(:ok)
      expect(json["code"]).to be_present
      expect(json["user"]["role"]).to eq("guest")
    end
  end

  describe "POST /users/code/renew" do
    it "returns 401 when not logged in" do
      sign_out
      post "/users/code/renew"
      expect(response).to have_http_status(:unauthorized)
    end
  end

  describe "PUT /users/:id" do
    let(:user) { create(:user, name: "old-name", role: "guest") }

    it "returns 401 when current_user id mismatch" do
      sign_in_as(create(:user))
      put "/users/#{user.id}", params: { name: "new-name" }
      expect(response).to have_http_status(:unauthorized)
    end

    it "returns 400 when name is blank" do
      sign_in_as(user)
      put "/users/#{user.id}", params: { name: "   " }
      expect(response).to have_http_status(:bad_request)
    end

    it "updates name and returns 201 with user slice" do
      sign_in_as(user)
      put "/users/#{user.id}", params: { name: "new-name" }

      expect(response).to have_http_status(:created)
      expect(json["id"]).to eq(user.id)
      expect(json["name"]).to eq("new-name")

      user.reload
      expect(user.name).to eq("new-name")
    end
  end

  describe "POST /users/verify" do
    it "returns valid:false when code not found" do
      post "/users/verify", params: { code: "nope" }
      expect(response).to have_http_status(:ok)
      expect(json["valid"]).to eq(false)
    end

    it "creates IpAddress and UserIp, and returns valid:true with user slice" do
      user = create(:user, inheritance_code: SecureRandom.uuid, role: "guest")

      # request.remote_ip を固定
      allow_any_instance_of(ActionDispatch::Request).to receive(:remote_ip).and_return("203.0.113.10")

      expect {
        post "/users/verify", params: { code: user.inheritance_code }
      }.to change(UserIp, :count).by(1)

      expect(response).to have_http_status(:ok)
      expect(json["valid"]).to eq(true)
      expect(json["user"]["id"]).to eq(user.id)
      expect(json["user"]["inheritance_code"]).to eq(user.inheritance_code)
      expect(json["user"]["role"]).to eq("guest")

      # ついでに IpAddress もできてることを確認（ipの保存形式がバイナリでも count で見れる）
      expect(IpAddress.count).to be >= 1
    end

    it "is idempotent for same user+ip (does not create duplicate UserIp)" do
      user = create(:user, inheritance_code: SecureRandom.uuid, role: "guest")
      allow_any_instance_of(ActionDispatch::Request).to receive(:remote_ip).and_return("203.0.113.10")

      post "/users/verify", params: { code: user.inheritance_code }
      expect(response).to have_http_status(:ok)

      expect {
        post "/users/verify", params: { code: user.inheritance_code }
      }.not_to change(UserIp, :count)

      expect(response).to have_http_status(:ok)
      expect(json["valid"]).to eq(true)
    end
  end

  describe "GET /users/me" do
    it "returns 404 when code not found" do
      get "/users/me", params: { code: "nope" }
      expect(response).to have_http_status(:not_found)
    end

    it "returns user slice when found" do
      user = create(:user, inheritance_code: SecureRandom.uuid, name: "me", role: "guest")
      get "/users/me", params: { code: user.inheritance_code }

      expect(response).to have_http_status(:ok)
      expect(json["id"]).to eq(user.id)
      expect(json["name"]).to eq("me")
      expect(json["inheritance_code"]).to eq(user.inheritance_code)
      expect(json["role"]).to eq("guest")
    end
  end
end
