contract Bibiz is ERC721A, Ownable, VRFConsumerBase {
  using Strings for uint256;

  uint256 public constant MAX_SUPPLY = 6969;
  uint256 public constant MAX_MINT_PER_WALLET = 5;
  address public constant LINK_ADDRESS = 0x514910771AF9Ca656af840dff83E8264EcF986CA;
  address public constant VRF_COORDINATOR_ADDRESS = 0xf0d54349aDdcf704F77AE15b96510dEA15cb7952;
  bytes32 internal constant KEY_HASH = 0xAA77729D3466CA35AE8D28B3BBAC7CC36A5031EFDC430821C02BC31A238AF445;
  uint256 private constant fee = 2 ether;

  string public unrevealedURI;
  string public baseURI;

  uint256 public cost = 0.049 ether;
  bool public paused = true;
  bool public revealed = false;
  uint256 public tokenOffset;

  constructor(
    string memory _name,
    string memory _symbol,
    string memory _unrevealedURI
  ) ERC721A(_name, _symbol) VRFConsumerBase(VRF_COORDINATOR_ADDRESS, LINK_ADDRESS) {
    unrevealedURI = _unrevealedURI;
  }

  function mint(uint256 quantity) external payable {
    require(quantity > 0, "Mint quantity less than 1.");
    require(totalSupply() + quantity <= MAX_SUPPLY, "Cannot exceed max mint amount.");
    require(_numberMinted(msg.sender) <= MAX_MINT_PER_WALLET, "Cannot exeeds 3 quantity per wallet.");

    if (msg.sender != owner()) {
      require(!paused, "Sale is currently paused.");
      require(msg.value == quantity * cost, "insufficient funds");
    }

    _safeMint(msg.sender, quantity);
  }

  /**
   * @dev See {IERC721Metadata-tokenURI}.
   */
  function tokenURI(uint256 tokenId) public view override returns (string memory) {
    require(!_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

    if (!revealed) return _baseURI();

    uint256 shiftedTokenId = (tokenId + tokenOffset) % MAX_SUPPLY;
    return string(abi.encodePacked(_baseURI(), shiftedTokenId.toString()));
  }

  /**
   * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
   * token will be the concatenation of the `baseURI` and the `tokenId`. Empty
   * by default, can be overriden in child contracts.
   */
  function _baseURI() internal view override returns (string memory) {
    return baseURI;
  }

  function requestOffset() public onlyOwner returns (bytes32 requestId) {
    LINK.transferFrom(owner(), address(this), fee);
    require(tokenOffset == 0, "Random offset already established");
    return requestRandomness(KEY_HASH, fee);
  }

  function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {
    require(!revealed);
    tokenOffset = randomness % MAX_SUPPLY;
  }

  function setCost(uint256 _newCost) public onlyOwner {
    cost = _newCost;
  }

  function pause(bool _state) public onlyOwner {
    paused = _state;
  }

  function reveal() public onlyOwner {
    revealed = true;
  }

  function setBaseURI(string memory _newBaseURI) public onlyOwner {
    baseURI = _newBaseURI;
  }

  function withdraw() public payable onlyOwner {
    (bool success, ) = payable(msg.sender).call{ value: address(this).balance }("");
    require(success);
  }
}
function tokenURI(uint256 tokenId) public view override returns (string memory) {
  require(!_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

  if (!revealed) return _baseURI();

  uint256 shiftedTokenId = (tokenId + tokenOffset) % MAX_SUPPLY;
  return string(abi.encodePacked(_baseURI(), shiftedTokenId.toString()));
}

/**
 * @dev See {IERC721Metadata-tokenURI}.
 */